1
0
Fork 0

Merging upstream version 1.4.1+dfsg.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-14 08:08:15 +02:00
parent 419af0eb9f
commit a9eef38502
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
9 changed files with 167 additions and 44 deletions

View file

@ -0,0 +1,6 @@
version: v1.0
allowed_secrets:
- filepath_literal: "docs/labs/lab07-aaa/svc_account_misc.py"
secret_literal: "9bfb39ff892c81d6ac9f25ff95d0389719595feb"
category: FALSE_POSITIVE
reason: Example token in documentation example file

3
.gitignore vendored
View file

@ -54,3 +54,6 @@ docs/_build/
docs/_modules/modules_by_category.rst
docs/_modules/list_of_*.rst
docs/_modules/*_module.rst
# .DS_Store
.DS_Store

View file

@ -20,3 +20,4 @@ exclude Jenkinsfile
exclude pre-commit.sh
exclude report
exclude htmlcov
recursive-exclude .arista *.yaml

View file

@ -75,9 +75,10 @@ using the API methods.
### Requirements
- Python 2.7 or later
- Python 3.7 or later
- Python logging module
- Python requests module version 1.0.0 or later
- Python requests module with socks version 2.27.0 or later
- Python packaging module version 23.2 or later
## Installation

View file

@ -1 +1 @@
1.4.0
1.4.1

View file

@ -32,5 +32,5 @@
''' RESTful API Client class for Cloudvision(R) Portal
'''
__version__ = '1.4.0'
__version__ = '1.4.1'
__author__ = 'Arista Networks, Inc.'

View file

@ -3930,6 +3930,15 @@ class CvpApi():
'time': '2022-05-03T15:38:53.725014447Z', 'type': 'INITIAL'}, ...]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
if self.cvp_version_compare('>=', 14.0, msg):
url = '/api/resources/serviceaccount/v1/Token/all'
self.log.debug(f"v14 {url}")
# Pull list of tokens out of data key of return for new resource APIs
resp = self.clnt.get(url)
tokens = []
if "data" in resp:
tokens = resp["data"]
return tokens
if self.cvp_version_compare('>=', 7.0, msg):
url = '/api/v3/services/arista.serviceaccount.v1.TokenService/GetAll'
self.log.debug(f"v7 {url}")
@ -3939,6 +3948,8 @@ class CvpApi():
def svc_account_token_get_one(self, token_id):
''' Get a service account token's state using Resource APIs
Supported versions: CVP 2021.3.0 or newer and CVaaS.
Args:
token_id (string): The id of the service account token.
Returns:
response (list): Returns a list of dict that contains...
Ex: [{'value': {'key': {'id': 'randomId'}, 'user': 'string',
@ -3947,11 +3958,16 @@ class CvpApi():
'time': '2022-05-03T15:38:53.725014447Z', 'type': 'INITIAL'}]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
if self.cvp_version_compare('>=', 14.0, msg):
endpoint = '/api/resources/serviceaccount/v1/Token'
query_param = f"?key.id={token_id}"
self.log.debug(f'v14 {endpoint + query_param}')
return self.clnt.get(endpoint + query_param)
if self.cvp_version_compare('>=', 7.0, msg):
endpoint = '/api/v3/services/arista.serviceaccount.v1.TokenService/GetOne'
payload = {"key": {"id": token_id}}
url = '/api/v3/services/arista.serviceaccount.v1.TokenService/GetOne'
self.log.debug(f"v7 {url} {payload}")
return self.clnt.post(url, data=payload)
self.log.debug(f'v7 {endpoint} {payload}')
return self.clnt.post(endpoint, data=payload)
return None
def svc_account_token_delete(self, token_id):
@ -3965,11 +3981,15 @@ class CvpApi():
'time': '2022-07-26T15:29:03.687167871Z'}]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
if self.cvp_version_compare('>=', 14.0, msg):
endpoint = f'/api/resources/serviceaccount/v1/TokenConfig?key.id={token_id}'
self.log.debug(f'v14 {endpoint}')
return self.clnt.delete(endpoint)
if self.cvp_version_compare('>=', 7.0, msg):
endpoint = '/api/v3/services/arista.serviceaccount.v1.TokenConfigService/Delete'
payload = {"key": {"id": token_id}}
url = '/api/v3/services/arista.serviceaccount.v1.TokenConfigService/Delete'
self.log.debug(f"v7 {url} {payload}")
return self.clnt.post(url, data=payload)
self.log.debug(f'v7 {endpoint} {payload}')
return self.clnt.post(endpoint, data=payload)
return None
def svc_account_token_set(self, username, duration, description):
@ -3987,14 +4007,31 @@ class CvpApi():
'description': 'cvprac test',
'valid_for': '550s', 'token': '<ey...>'}]
'''
payload = {'value': {'description': description,
'user': username,
'valid_for': duration}}
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
if self.cvp_version_compare('>=', 14.0, msg):
payload = {
'key': {
'id': ''
},
'description': description,
'user': username,
'validFor': duration,
'token': ''
}
endpoint = '/api/resources/serviceaccount/v1/TokenConfig'
self.log.debug(f'v14 {endpoint} {payload}')
return self.clnt.post(endpoint, data=payload)
if self.cvp_version_compare('>=', 7.0, msg):
url = '/api/v3/services/arista.serviceaccount.v1.TokenConfigService/Set'
self.log.debug(f"v7 {url} {payload}")
return self.clnt.post(url, data=payload)
payload = {
'value': {
'description': description,
'user': username,
'valid_for': duration
}
}
endpoint = '/api/v3/services/arista.serviceaccount.v1.TokenConfigService/Set'
self.log.debug(f'v7 {endpoint} {payload}')
return self.clnt.post(endpoint, data=payload)
return None
def svc_account_get_all(self):
@ -4005,13 +4042,21 @@ class CvpApi():
Ex: [{'value': {'key': {'name': 'ansible'}, 'status': 'ACCOUNT_STATUS_ENABLED',
'description': 'lab-tests', 'groups': {'values': ['network-admin']}},
'time': '2022-02-10T04:28:14.251684869Z', 'type': 'INITIAL'}, ...]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
if self.cvp_version_compare('>=', 14.0, msg):
endpoint = '/api/resources/serviceaccount/v1/Account/all'
self.log.debug(f"v14 {endpoint}")
# Pull list of accounts out of data key of return for new resource APIs
resp = self.clnt.get(endpoint)
svc_accounts = []
if "data" in resp:
svc_accounts = resp["data"]
return svc_accounts
if self.cvp_version_compare('>=', 7.0, msg):
url = '/api/v3/services/arista.serviceaccount.v1.AccountService/GetAll'
self.log.debug(f"v7 {url}")
return self.clnt.post(url)
endpoint = '/api/v3/services/arista.serviceaccount.v1.AccountService/GetAll'
self.log.debug(f"v7 {endpoint}")
return self.clnt.post(endpoint)
return None
def svc_account_get_one(self, username):
@ -4026,13 +4071,35 @@ class CvpApi():
'time': '2022-02-10T04:28:14.251684869Z'}]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
if self.cvp_version_compare('>=', 14.0, msg):
endpoint = '/api/resources/serviceaccount/v1/Account'
query_param = f"?key.name={username}"
self.log.debug(f"v14 {endpoint + query_param}")
return self.clnt.get(endpoint + query_param)
if self.cvp_version_compare('>=', 7.0, msg):
endpoint = '/api/v3/services/arista.serviceaccount.v1.AccountService/GetOne'
payload = {"key": {"name": username}}
url = '/api/v3/services/arista.serviceaccount.v1.AccountService/GetOne'
self.log.debug(f"v7 {url} {payload}")
return self.clnt.post(url, data=payload)
self.log.debug(f"v7 {endpoint} {payload}")
return self.clnt.post(endpoint, data=payload)
return None
def _get_valid_role_ids(self, roles):
''' Helper function to validate and retrieve role IDs based on provided roles.
Args:
roles (list): The list of role names.
Returns:
role_ids (list): The list of role IDs.
'''
role_ids = []
all_roles = self.get_roles()
for role in all_roles['roles']:
if role['key'] in roles or role['name'] in roles:
role_ids.append(role['key'])
if len(roles) != len(role_ids):
self.log.warning(f"Not all provided roles {roles} are valid. "
f"Only using the found valid roles {role_ids}")
return role_ids
def svc_account_set(self, username, description, roles, status):
''' Create a service account using Resource APIs.
Supported versions: CVP 2021.3.0 or newer and CVaaS.
@ -4056,23 +4123,26 @@ class CvpApi():
'time': '2022-07-26T18:19:55.392173445Z'}]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
# Retrieve valid role IDs
role_ids = self._get_valid_role_ids(roles)
if self.cvp_version_compare('>=', 14.0, msg):
payload = {
'description': description,
'groups': {'values': role_ids},
'key': {'name': username},
'status': status
}
endpoint = '/api/resources/serviceaccount/v1/AccountConfig'
self.log.debug(f"v14 {endpoint} {payload}")
return self.clnt.post(endpoint, data=payload)
if self.cvp_version_compare('>=', 7.0, msg):
role_ids = []
all_roles = self.get_roles()
for role in all_roles['roles']:
if role['key'] in roles or role['name'] in roles:
role_ids.append(role['key'])
if len(roles) != len(role_ids):
self.log.warning(f"Not all provided roles {roles} are valid. "
f"Only using the found valid roles {role_ids}")
payload = {'value': {'description': description,
'groups': {'values': role_ids},
'key': {'name': username},
'status': status}}
url = '/api/v3/services/arista.serviceaccount.v1.AccountConfigService/Set'
self.log.debug(f"v7 {url} {payload}")
return self.clnt.post(url, data=payload)
endpoint = '/api/v3/services/arista.serviceaccount.v1.AccountConfigService/Set'
self.log.debug(f"v7 {endpoint} {payload}")
return self.clnt.post(endpoint, data=payload)
return None
def svc_account_delete(self, username):
@ -4086,11 +4156,15 @@ class CvpApi():
'time': '2022-07-26T18:26:53.637425846Z'}]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
if self.cvp_version_compare('>=', 14.0, msg):
endpoint = f'/api/resources/serviceaccount/v1/AccountConfig?key.name={username}'
self.log.debug(f"v14 {endpoint}")
return self.clnt.delete(endpoint)
if self.cvp_version_compare('>=', 7.0, msg):
payload = {"key": {"name": username}}
url = '/api/v3/services/arista.serviceaccount.v1.AccountConfigService/Delete'
self.log.debug(f"v7 {url} {payload}")
return self.clnt.post(url, data=payload)
endpoint = '/api/v3/services/arista.serviceaccount.v1.AccountConfigService/Delete'
self.log.debug(f"v7 {endpoint} {payload}")
return self.clnt.post(endpoint, data=payload)
return None
def svc_account_delete_expired_tokens(self):
@ -4105,11 +4179,21 @@ class CvpApi():
'time': '2022-07-26T18:30:28.022504853Z','type': 'INITIAL'},
{'value': {'key': {'id': '2f6325d9c'},...]
'''
msg = 'Service Account Resource APIs are supported from 2021.3.0+.'
valid_until_format = "valid_until"
resource_api_schema = False
if self.cvp_version_compare('>=', 14.0, msg):
resource_api_schema = True
valid_until_format = "validUntil"
tokens = self.svc_account_token_get_all()
expired_tokens = []
for tok in tokens:
token = tok['value']
if datetime.strptime(token['valid_until'], "%Y-%m-%dT%H:%M:%SZ") < datetime.utcnow():
self.svc_account_token_delete(token['key']['id'])
if resource_api_schema:
token_data = tok['result']['value']
else:
token_data = tok['value']
if (datetime.strptime(token_data[valid_until_format], "%Y-%m-%dT%H:%M:%SZ") <
datetime.utcnow()):
self.svc_account_token_delete(token_data['key']['id'])
expired_tokens.append(tok)
return expired_tokens

View file

@ -123,7 +123,7 @@ class CvpClient():
# Maximum number of times to retry a get or post to the same
# CVP node.
NUM_RETRY_REQUESTS = 3
LATEST_API_VERSION = 9.0
LATEST_API_VERSION = 14.0
def __init__(self, logger='cvprac', syslog=False, filename=None,
log_level='INFO'):
@ -213,7 +213,13 @@ class CvpClient():
For CVP versions 2020.2.4 through 2021.1.x, use api version 5.0
For CVP versions 2021.2.x, use api version 6.0
For CVP versions 2021.3.x, use api version 7.0
For CVP versions 2022.1.0 and beyond, use api version 8.0
For CVP versions 2022.x.x, use api version 8.0
For CVP versions 2023.1.x, use api version 9.0
For CVP versions 2023.2.x, use api version 10.0
For CVP versions 2023.3.x, use api version 11.0
For CVP versions 2024.1.x, use api version 12.0
For CVP versions 2024.2.x, use api version 13.0
For CVP versions 2024.3.x and beyond, use api version 14.0
Args:
version (str): The CVP version in use.
@ -221,6 +227,11 @@ class CvpClient():
self.version = version
self.log.info('Version %s', version)
# Set apiversion to latest available API version for CVaaS
# Set apiversion to 14.0 for 2024.3.x
# Set apiversion to 13.0 for 2024.2.x
# Set apiversion to 12.0 for 2024.1.x
# Set apiversion to 11.0 for 2023.3.x
# Set apiversion to 10.0 for 2023.2.x
# Set apiversion to 9.0 for 2023.1.x
# Set apiversion to 8.0 for 2022.1.x - 2022.3.x
# Set apiversion to 7.0 for 2021.3.x
@ -242,7 +253,13 @@ class CvpClient():
' Appending 0. Updated Version String - %s',
".".join(version_components))
full_version = ".".join(version_components)
if parse(full_version) >= parse('2024.1.0'):
if parse(full_version) >= parse('2024.3.0'):
self.log.info('Setting API version to v14')
self.apiversion = 14.0
elif parse(full_version) >= parse('2024.2.0'):
self.log.info('Setting API version to v13')
self.apiversion = 13.0
elif parse(full_version) >= parse('2024.1.0'):
self.log.info('Setting API version to v12')
self.apiversion = 12.0
elif parse(full_version) >= parse('2023.3.0'):

View file

@ -0,0 +1,11 @@
######
v1.4.1
######
2025-5-8
Enhancements
^^^^^^^^^^^^
* Add support new service account resource APIs. (`281 <https://github.com/aristanetworks/cvprac/pull/281>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Updates for CVP 2024.3.0 suppot. (`282 <https://github.com/aristanetworks/cvprac/pull/282/>`_) [`mharista <https://github.com/mharista>`_]