5. Using the GCENTER API

It can be used in three different ways:

  • Via SWAGGER

  • Via CURL](#use-via-curl)

  • Via Package python]( #use-via-package-python)

5.1. Use via swagger

By connecting to your GCenter, access the URL https://hostnameGCENTER/docs/swagger/ You will be able to access the documentation of all our API endpoints.

By clicking on the "try it out" button, you can directly test requests. The tool will also generate queries for you to use with curl.

Note

A known bug affects the /api/alerts endpoint (see the GCenter release note). It is recommended to favour data querying by the elasticsearch API on the /api/data/es/search endpoint.

5.2. Use via CURL

For a user who is called username and has operator rights**.

Retrieving the API token:


curl -X POST "https://<hostname>/api/auth/login" -H "accept: application/json" -H "Content-Type: application/json" -d "{ \"username\": \"username\", \"password\": \"password\"}" -k

Response:


{"token":"urxn5hlezbk3vnlgq1t45rifhg0vi951","expiration_date":"2021-04-13T16:26:45.743826"}

The expiration date is determined by the duration set in Administrators > Configuration > Session age settings in the GCenter webui

Sending a request:


curl -X POST "https://<hostname>/api/<endpoint> -H "accept: application/json" -H "Content-Type: application/json" -H "API-KEY: x0zc5py1e2lrppe6ws0kgc8le0oxm9hg" -d "{\"test\": \"test\"}" -k

Example of a request that queries elasticsearch on its suricata* indexes and retrieves 100 logs over the last 24 hours:


curl -X POST "https://<hostname>/api/<endpoint> -H "accept: application/json" -H "Content-Type: application/json" -H "API-KEY: x0zc5py1e2lrppe6ws0kgc8le0oxm9hg" -d "{ \"size\": 100, \"query\": { \"bool\": { \"must\": [], \"filter\": [ { \"match_all\": {} }, { \"range\": { \"@timestamp\": { \"gte\": \"now-24h\", \"lte\": \"now\" } } } ], \"should\": [], \"must_not\": [] } } }" -k

5.3. Use via python package

This package is a python library implementing many of the endpoints of the GCenter API.

GCenter API package: gwapi-master.tar.gz

5.3.1. Installation

The prerequisites:

  • python>=3.5

  • requests==2.25.1

  • urllib3==1.26.6

  • packaging==20.9

The package installation is achieved with the pip utility:

pip3 install gwapi.tar.gz

5.3.2. Use

5.3.2.1. Import

To use the library, simply import the gwapi package:

>>> import gwapi

5.3.2.2. Documentation

To display the documentation for any given function:

>>> help(gwapi.GcenterApi.auth)
Help on auth function in gwapi.api module:

auth(self, user: 'str', password: 'str') -> 'bool'
    Authentication through the Gcenter API.

    Returns:
        Return true if authenticated.

    Raises:
        RequestException: If status_code!= 200.

5.3.2.3. List the library functions

To list all of the library's functions:

>>> for func in [func for func in dir(gwapi.GcenterApi) if callable(getattr(gwapi.GcenterApi, func)) and not func.startswith("__") and not func.startswith("_")]:
...   print(func)
apply_gcap
auth
...

5.3.2.4. Authentication

All API endpoints require authentication.

Authenticate via the GCenter API:

>>> api = gwapi.GcenterApi(ip="X.X.X.X", version="2.5.3.101")
>>> api.auth(user="username", password="password")
True

5.3.2.5. Elasticsearch query

The elasticsearch API alone is implemented via the GCenter API.

Example of elasticsearch queries via the API:

  • Number/List of files reconstructed by gcap over a 24 hour period:

query = {
  "size": 10
  "query": {
    "bool": {
      "must": {
        "match": {
         "fileinfo.stored": "true"
        }
      },
      "filter": {
        "range": {
          "@timestamp": {
              "gte": "now-24h",
              "lte": "now"
          }
        }
      }
    }
  }
}
api.get_es_query(index="suricata", query=query)['hits']['hits']
api.get_es_count(index="suricata", query=query)
  • Number/List of malcore alerts in order of severity over a 24-hour period:

query = {
  "size": 10
  "query": {
    "bool": {
      "must": {
        "match": {
         "event_type": "malware"
        }
      },
      "filter": {
        "range": {
          "@timestamp": {
              "gte": "now-24h",
              "lte": "now"
          }
        }
      }
    }
  },
  "sort": {
    "severity": "desc"
  }
}
api.get_es_query(index="malware", query=query)['hits']['hits']
api.get_es_count(index="malware", query=query)
  • Number/List of shellcode alerts in order of severity over a 24-hour period:

query = {
  "size": 10
  "query": {
    "bool": {
      "must": {
        "match": {
         "event_type": "shellcode"
        }
      },
      "filter": {
        "range": {
          "@timestamp": {
              "gte": "now-24h",
              "lte": "now"
          }
        }
      }
    }
  },
  "sort": {
    "severity": "desc"
  }
}
api.get_es_query(index="codebreaker", query=query)['hits']['hits']
api.get_es_count(index="codebreaker", query=query)
  • Number/List of powershell alerts in order of severity over a 24-hour period:

query = {
  "size": 10
  "query": {
    "bool": {
      "must": {
        "match": {
         "event_type": "powershell"
        }
      },
      "filter": {
        "range": {
          "@timestamp": {
              "gte": "now-24h",
              "lte": "now"
          }
        }
      }
    }
  },
  "sort": {
    "scores.analysis": "desc"
  }
}
api.get_es_query(index="codebreaker", query=query)['hits']['hits']
api.get_es_count(index="codebreaker", query=query)
  • Number/list of sigflow alerts in order of severity over a 24-hour period:

query = {
  "size": 10
  "query": {
    "bool": {
      "must": {
        "match": {
         "event_type": "alert"
        }
      },
      "filter": {
        "range": {
          "@timestamp": {
              "gte": "now-24h",
              "lte": "now"
          }
        }
      }
    }
  },
  "sort": {
    "alert.severity": "desc"
  }
}
api.get_es_query(index="suricata", query=query)['hits']['hits']
api.get_es_count(index="suricata", query=query)
  • Top 10 signatures of Sigflow alerts:

query = {
  "size": 0
  "query": {
    "match": {
     "event_type": "alert"
    }
  },
  "aggs": {
    "signature": {
      "terms": {
        "field": "alert.signature",
        "order": { "_count": "desc"},
        "size": 10
      }
    }
  }
}
api.get_es_query(index="suricata", query=query)['aggregations']['signature']['buckets']
  • Top 10 IP source addresses for Sigflow alerts:

query = {
  "size": 0
  "query": {
    "match": {
     "event_type": "alert"
    }
  },
  "aggs": {
    "src_ip": {
      "terms": {
        "field": "src_ip",
        "order": { "_count": "desc"},
        "size": 10
      }
    }
  }
}
api.get_es_query(index="suricata", query=query)['aggregations']['src_ip']['buckets']
  • Top 10 shellcode types:

query = {
  "size": 0
  "query": {
    "match": {
     "event_type": "shellcode"
    }
  },
  "aggs": {
    "sub_type": {
      "terms": {
        "field": "sub_type",
        "order": { "_count": "desc"},
        "size": 10
      }
    }
  }
}
api.get_es_query(index="codebreaker", query=query)['aggregations']['sub_type']['buckets']
  • Top 10 malware types:

query = {
  "size": 0
  "query": {
    "match": {
     "event_type": "malware"
    }
  },
  "aggs": {
    "detail_threat_found": {
      "terms": {
        "field": "detail_threat_found",
        "order": { "_count": "desc"},
        "size": 10
      }
    }
  }
}
api.get_es_query(index="malware", query=query)['aggregations']['detail_threat_found']['buckets']
  • Ranking of the source/ destination IP addresses of Sigflow alerts in descending order:

query = {
  "size": 0
  "query": {
    "match": {
     "event_type": "alert"
    }
  },
  "aggs": {
    "couple": {
      "composite": {
        "sources":[
          {
            "src_ip":{
              "terms":{
                "field": "src_ip",
                "order": "desc"
              }
            }
          },
          {
            "dest_ip":{
              "terms":{
                "field": "dest_ip",
                "order": "desc"
              }
            }
          }
        ],
        "size": 65535
      }
    }
  }
}
api.get_es_query(index="suricata", query=query)['aggregations']['couple']['buckets']
  • Count/List the last 10 alerts having the status Infected in malcore:

>>> query = {
...   "size": 10
...   "query": {
...     "match": {
...       "state": "Infected"
...     }
...   }
... }
>>> api.get_es_query(index="malware", query=query)
[{'_index': 'malware-2021.06.29-000007', '_type': '_doc', '_id': 'uGn0VnoBfk3pKEfjbjFz', '_score': 0.00024064493, '_source': {'timestamp_detected': '2021-06-29T08:37:09.043Z'...}]
>>> api.get_es_count(index="malware", query=query)
4189

5.3.2.6. Alertes

The API enables GCenter alerts to be displayed in two forms:

  • The latest alerts sent by the Gcaps (sigflow, malcore, codebreaker).

  • The last alerts sent by the Gcaps in the form of a cluster: alerts that occurred in the same time frame, i.e. the last hour or the last day for example, and that are all linked to the same IP address.

Retrieve GCenter alerts:

# Display alerts in RAW format
>>> from datetime import datetime, timedelta
>>> import json
>>> delta = datetime.utcnow() - timedelta(days=5)
>>> alerts = api.get_gcenter_alerts(date_from=delta.isoformat(),
...                                date_to=datetime.utcnow().isoformat(),
...                                gcap_id="all",
...                                ip="1.1.1.1",
...                                sort_by="date_asc",
...                                risk_min=0,
...                                risk_max=10)
>>> print(json.dumps(alerts, indent=4))
[
    {
        "id": "2021-06-29T08:28:21.932Z",
        "name": "ASCII text, with very long lines",
        "date": "2021-06-29T08:27:21",
        "gcap": {
            "id": 1
            "fqdn": "gcap.example.com",
            "is_paired": true
        },
        "description": "Infected: JS/Downloader.S200, JS:Trojan.JS.Downloader.AZ, JS/Downldr.CZ!Eldorado, JS/Kryptik.AYN trojan, JS:Trojan.JS.Downloader.AZ (B)",
        "src_ip": "1.1.1.1",
        "dest_ip": "2.2.2.2",
        "risk": 13
        "type": "malcore"
    },
    {
        "id": "2021-06-29T08:31:22.816Z",
        "name": "ASCII text, with very long lines",
        "date": "2021-06-29T08:30:53",
        "gcap": {
            "id": 1
            "fqdn": "gcap.example.com",
            "is_paired": true
        },
        "description": "Infected: JS/Downloader.S200, JS:Trojan.JS.Downloader.AZ, JS/Downldr.CZ!Eldorado, JS/Kryptik.AYN trojan, JS:Trojan.JS.Downloader.AZ (B)",
        "src_ip": "1.1.1.1",
        "dest_ip": "2.2.2.2",
        "risk": 13
        "type": "malcore"
    }
]
# Display alerts in Cluster format
>>> alerts = api.get_gcenter_clusters_alerts(date_from=delta.isoformat(),
...                                 date_to=datetime.utcnow().isoformat(),
...                                 gcap_id="all",
...                                 ip="1.1.1.1",
...                                 sort_by="src",
...                                 frequency="hour")
>>> print(json.dumps(alerts, indent=4))
[
    {
        "id": "1.1.1.1-2021-06-29T08:00:00.000Z",
        "ip": "1.1.1.1",
        "number_alerts": 1
        "average_risk": 1.0
        "risk_score": 1
        "date": "2021-06-29T08:00:00",
        "description": "The cluster 1.1.1.1 has 1 alert registered the 2021-06-29 08:00:00 (malcore and codebreaker: 1)",
        "malcore_codebreaker": 1
        "type_ip": "src",
        "gcap": {
            "id": 1
            "fqdn": "gcap.example.com",
            "is_paired": true
        }
    }
]

5.3.2.7. Data export

Data export includes netdata and syslog functions.

Netdata export configuration:

# Netdata export configuration
>>> api.set_netdata(enabled=True, ip="10.10.10.10", port=80, iface="mgmt0", key="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")
# Disabling Netdata export
>>> api.set_netdata(enabled=False)

Syslog export configuration 1:

# Configuration of the syslog export general tab.
>>> api.set_syslog_general(id=1, hostname="10.10.10.10", port=514)
# Configuring filters for syslog export 1.
>>> api.clear_syslog_filters(id=1)
>>> api.set_syslog_filters(id=1, ips=["10.10.10.10"], gcap=[gcap_choice], protocols=["dns", "http"])
# Configuring certificates for syslog export 1. The certificates must be in PEM format.
>>> api.set_syslog_certificate(id=1, cert="-----BEGIN CERTIFICATE-----...", cert_key="-----BEGIN RSA PRIVATE KEY-----", ca="-----BEGIN CERTIFICATE-----...")
# Disabling syslog export 1.
>>> api.disable_syslog(id=1)

5.3.2.8. Gcap Profiles

The Gcap Profiles section of the Operators menu is partially configurable via the API. The "Detection Rulesets" and "Base Variables" sections are configurable.

To apply changes to gcap:

>>> api.apply_gcap(gcap_id=1)
{'detail': 'Gcap config file updated with success'}

Functions not requiring any changes to be applied:

# List the Gcaps associated with GCenter
>>> api.get_gcaps()
[{'id': 1, 'fqdn': 'gcap.example.com', 'is_paired': True, 'last_rule_update': '2021-07-01T13:42:03.709091', 'status': 'online'}]
# Display the Gcap data associated with GCenter
>>> api.get_gcap_by_id(gcap_id=1)
{'id': 1, 'fqdn': 'gcap.example.com', 'is_paired': True, 'last_rule_update': '2021-07-01T13:42:03.709091', 'status': 'online'}
# Display the template associated with Gcaps
>>> api.get_gcap_template()
{'profile': 'intuitio'}
# Change the template associated with the Gcaps among the values: ["minimal", "balanced", "lpm", "paranoid", "intuitio"]
>>> api.set_gcap_template(template="balanced")
{'profile': 'balanced'}
# Display the Gcap's interfaces
>>> api.get_gcap_interfaces(gcap_id=1)
[
    {
        "enabled": true,
        "name": "mon0",
        "mtu": 1500
        "is_cluster": false,
        "cluster_interfaces": [
            "mon0"
        ]
    }
]
# Display the single-tenant configuration
>>> api.get_gcap_single_tenant(gcap_id=1)
{'enabled': False, 'enable_shellcode': True, 'enable_powershell': True}
# Display the multi-tenant configuration
>>> api.get_gcap_multi_tenant(gcap_id=1)
{'enabled': True, 'ruleset': [{'id': 502, 'ruleset': 3, 'codebreaker_shellcode': True, 'codebreaker_powershell': True, 'name': 'mon1'}], 'is_by_interface': True}
>>> api.get_gcap_profile(gcap_id=1)
{'files_hash': ['md5'], 'max_pending_packets': 4096, 'file_store_stream_depth_enable': True, 'file_store_stream_depth_mb': 10, 'stream_memcap_b': 32000000000, 'stream_prealloc_sessions': 1000000, 'stream_reassembly_memcap_b': 16000000000, 'stream_reassembly_depth_mb': 10, 'stream_reassembly_toserver_chunk_size_b': 2560, 'stream_reassembly_toclient_chunk_size_b': 2560, 'flow_memcap': 17179869184, 'flow_prealloc': 1048576, 'stream_reassembly_randomize_chunk_size': True, 'xff_enable': True, 'xff_mode': 'extra-data', 'xff_deployment': 'reverse', 'xff_header': 'X-Forwarded-For', 'payload': True, 'payload_buffer_size': 4096, 'payload_printable': True, 'packet': True, 'file_resend_interval': 600, 'http_body': False, 'http_body_printable': False, 'ftp_memcap': 10485760, 'smb_stream_depth': 10485760, 'http_enable': True, 'dns_udp_enable': True, 'dns_tcp_enable': True, 'tls_enable': True, 'smtp_enable': True, 'smb_enable': True, 'ssh_enable': True, 'netflow_enable': True, 'dnp3_enable': True, 'ftp_enable': True, 'dhcp_enable': True, 'ikev2_enable': True, 'krb5_enable': True, 'nfs_enable': True, 'tftp_enable': True, 'parsing_dcerpc_enabled': 1, 'parsing_dnp3_enabled': 1, 'parsing_dns_udp_enabled': 1, 'parsing_dns_tcp_enabled': 1, 'parsing_ftp_enabled': 1, 'parsing_http_enabled': 1, 'parsing_modbus_enabled': 1, 'parsing_smb_enabled': 1, 'parsing_smtp_enabled': 1, 'parsing_ssh_enabled': 1, 'parsing_tls_enabled': 1, 'parsing_dhcp_enabled': 1, 'parsing_ikev2_enabled': 1, 'parsing_krb5_enabled': 1, 'parsing_nfs_enabled': 1, 'parsing_ntp_enabled': 1, 'parsing_tftp_enabled': 1}
# Show vlans configuration
>>> api.get_gcap_vlans(gcap_id=1)
[{'id': 496, 'ruleset': 3, 'codebreaker_shellcode': True, 'codebreaker_powershell': True, 'name': 'default'}, {'id': 497, 'ruleset': 3, 'codebreaker_shellcode': True, 'codebreaker_powershell': True, 'name': '120'}, {'id': 498, 'ruleset': 3, 'codebreaker_shellcode': False, 'codebreaker_powershell': False, 'name': '110'}]

Functions requiring changes to be applied:

# Configure the single-tenant
>>> api.set_gcap_single_tenant(
...     gcap_id=1,
...     enabled=True,
...     ruleset_id=3,
...     shellcode=True,
...     powershell=True
... )
{'enabled': True, 'ruleset': 3, 'enable_shellcode': True, 'enable_powershell': True}
# Configure multi-tenant per interface. It must be done for each interface.
>>> api.set_gcap_multi_tenant_interface(
...     gcap_id=1,
...     interface="mon0",
...     ruleset_id=3,
...     shellcode=True,
...     powershell=True
... )
{'enabled': True, 'ruleset': [{'ruleset': 3, 'codebreaker_shellcode': True, 'codebreaker_powershell': True, 'name': 'mon0'}], 'is_by_interface': True}
# Remove multi-tenant configuration (vlans + interfaces)
>>> api.reset_gcap_tenant(gcap_id=1)
True
# Configure the gcap variables. For the moment only the logging and protocol parsing configuration is implemented.
>>> PARSING_PROTOS = [
...     "dcerpc", "dhcp", "dnp3", "dns_udp", "dns_tcp", "ftp",
...     "http", "ikev2", "krb5", "modbus", "nfs", "ntp", "smb",
...     "smtp", "ssh", "tftp", "tls"
... ]
>>> LOGGING_PROTOS = [
...     "dhcp", "dnp3", "dns_udp", "dns_tcp", "ftp", "http", "ikev2",
...     "krb5", "netflow", "nfs", "smb", "smtp", "ssh", "tftp", "tls"
... ]
>>> for proto in PARSING_PROTOS:
...     api.set_gcap_profile(gcap_id=1, proto=proto, parsing=True, logging=None)
>>> for proto in LOGGING_PROTOS:
...     api.set_gcap_profile(gcap_id=1, proto=proto, parsing=None, logging=True)
# Add a vlan.
>>> api.set_gcap_vlan(
...     gcap_id=1,
...     vlan="110",
...     ruleset_id=3,
...     shellcode=False,
...     powershell=False
... )
{'id': 495, 'ruleset': 3, 'codebreaker_shellcode': False, 'codebreaker_powershell': False, 'name': '110'}
# Configure multi-tenant per vlan
>>> api.set_gcap_multi_tenant_vlan(
...     gcap_id=1,
...     vlan="110",
...     ruleset_id=3,
...     shellcode=False,
...     powershell=False
... )
{'enabled': True, 'ruleset': [{'ruleset': 3, 'codebreaker_shellcode': True, 'codebreaker_powershell': True, 'name': 'default'}, {'ruleset': 3, 'codebreaker_shellcode': True, 'codebreaker_powershell': True, 'name': '120'}, {'ruleset': 3, 'codebreaker_shellcode': False, 'codebreaker_powershell': False, 'name': '110'}], 'is_by_interface': False}
# Delete a vlan
>>> api.delete_gcap_vlan(
...     gcap_id=1,
...     vlan="110"
... )
True
# Modify the vlan configuration. The vlan must be deleted and recreated.
>>> api.delete_gcap_vlan(
...     gcap_id=1,
...     vlan="110"
... )
True
>>> api.set_gcap_vlan(
...     gcap_id=1,
...     vlan="110",
...     ruleset_id=3,
...     shellcode=False,
...     powershell=False
... )
{'id': 495, 'ruleset': 3, 'codebreaker_shellcode': False, 'codebreaker_powershell': False, 'name': '110'}

5.3.2.9. Licence

It is possible to configure and view the GCenter license via the API.

Configure the GCenter license:

>>> api.get_serial_number()
'XXXXXXX'
>>> api.get_licence()
{'key': 'XXX...', 'license_expiry_alert': 90, 'details': {'antimalware_engines': 16, 'cie': False, 'codebreaker': True, 'days_left': 7, 'end_date': '2021-07-08', 'expired': False, 'full': True, 'license_expiry_alert': 90, 'machine_learning': True, 'malcore': True, 'max_gcaps': 100, 'model': '', 'nozomi': False, 'registered_mail': 'trial@gatewatcher.com', 'registered_owner': 'Trial', 'retroact': True, 'serial_number': 'XXX', 'sigflow': True, 'start_date': '2021-07-01', 'valid': True}}
>>> api.set_licence(key="XXX", expiry_alert=90)

5.3.2.10. Network

It is possible to view the network configuration of the GCenter via the API.

# Display the configuration of all GCenter network interfaces
>>> api.get_gcenter_interfaces()
[{'name': 'mgmt0', 'fullname': 'mgmt0 - 3.3.3.3', 'hostname': '3.3.3.3'}, {'name': 'vpn0', 'fullname': 'vpn0 - 4.4.4.4', 'hostname': '4.4.4.4'}, {'name': 'icap0', 'fullname': 'icap0 - 5.5.5.5', 'hostname': '5.5.5.5'}, {'name': 'sup0', 'fullname': 'sup0 - 6.6.6.6', 'hostname': '6.6.6.6'}]
# Display the configuration of all GCenter network interfaces
>>> api.get_gcenter_interface_by_name("mgmt0")
{'name': 'mgmt0', 'fullname': 'mgmt0 - 3.3.3.3', 'hostname': '3.3.3.3'}

5.3.2.11. Malcore

It is possible to configure and view the Malcore settings via the API.

>>> api.set_malcore_settings(days=10, rescan=3, gbox=False)
>>> api.get_malcore_settings()
{'retroact_number_of_days_between_rescans': 10, 'retroact_number_of_rescan': 3, 'gbox_analysis': False}

5.3.2.12. Sigflow

**It is possible to view Sigflow rulesets via the API.

# List the rulesets associated with GCenter
>>> api.get_sigflow_rulesets()
[{'id': 3, 'name': 'ALL', 'descr': '', 'created_date': '2021-06-24T13:45:35.627132Z', 'has_files': True}]
# List only the rulesets whose files were generated
>>> api.get_sigflow_rulesets(with_files=True)
[{'id': 3, 'name': 'ALL', 'descr': '', 'created_date': '2021-06-24T13:45:35.627132Z', 'has_files': True}]
# Display the ruleset configuration associated with the GCenter
>>> api.get_sigflow_ruleset_by_id(ruleset_id=3)
{'id': 3, 'name': 'ALL', 'descr': '', 'created_date': '2021-06-24T13:45:35.627132Z', 'has_files': True}

5.3.2.13. Status

It is possible to view the status of GCenter components via the API.

Display the status of the GCenter components:

# Check that the API is working: no authentication required
>>> api.get_api_status()
True
# Display the GCenter status
>>> api.get_gcenter_status()
{'version': '2.5.3.101-XXXX', 'serial_number': 'XXXXXXX'}
# Display the GCenter's overall status and associated errors
>>> api.get_healthchecks_status()
{'healthy': 'Bad', 'errors': ['Malware Analysis Engine has one or more issues: Last known good status: 2021-06-25T12:58:46.336013']}
# View the update status
>>> api.get_updates_status()
{'status': 'Good', 'errors': []}
# Display the user's authentication status
>>> api.get_user_status()
{'message': 'success', 'authenticated': False}

5.3.2.14. User

It is possible to view GCenter user data via the API.

Display the GCenter user data:

# Display the data of all users
>>> api.get_users()
[{'id': 1, 'username': 'admin', 'roles': [{'name': 'gwrights.gcap_mgmt'}, {'name': 'gwrights.sigflow_mgmt'}, {'name': 'gwrights.user_mgmt'}, {'name': 'gwrights.gcenter_mgmt'}, {'name': 'gwrights.common'}, {'name': 'gwrights.dashboards'}, {'name': 'gwrights.samples'}], 'groups': []}, {'id': 2, 'username': 'operator', 'roles': [{'name': 'gwrights.dashboards'}, {'name': 'gwrights.sigflow_mgmt'}, {'name': 'gwrights.common'}, {'name': 'gwrights.samples'}], 'groups': [{'id': 2, 'name': 'operators'}]}, {'id': 3, 'username': 'administrator', 'roles': [{'name': 'gwrights.user_mgmt'}, {'name': 'gwrights.common'}, {'name': 'gwrights.gcenter_mgmt'}, {'name': 'gwrights.gcap_mgmt'}], 'groups': [{'id': 1, 'name': 'administrators'}]}]
# Display a user's data
>>> api.get_user_by_id(user_id=1)
{'id': 1, 'username': 'admin', 'roles': [{'name': 'gwrights.gcap_mgmt'}, {'name': 'gwrights.sigflow_mgmt'}, {'name': 'gwrights.user_mgmt'}, {'name': 'gwrights.gcenter_mgmt'}, {'name': 'gwrights.common'}, {'name': 'gwrights.dashboards'}, {'name': 'gwrights.samples'}], 'groups': []}