Skip to content

Commit

Permalink
Merge pull request gmr#123 from abaez/acl-1.5.0
Browse files Browse the repository at this point in the history
Acl 1.5.0
  • Loading branch information
gmr authored Aug 24, 2020
2 parents e8acd07 + e4b46d7 commit 39e6c17
Show file tree
Hide file tree
Showing 11 changed files with 690 additions and 44 deletions.
302 changes: 296 additions & 6 deletions consulate/api/acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,300 @@
from consulate.models import acl as model
from consulate.api import base
from consulate import exceptions
# from typing import List, Dict, Union

LOGGER = logging.getLogger(__name__)

# ServiceIdentity = Dict[str, Union[str, List[str]]]
# ServiceIdentities = List[ServiceIdentity]
# PolicyLink = Dict[str, str]
# PolicyLinks = List[PolicyLink]
# RoleLink = Dict[str, str]
# RoleLinks = List[RoleLink]


class ACL(base.Endpoint):
"""The ACL endpoints are used to create, update, destroy, and query ACL
tokens.
"""
def list_policies(self):
"""List all ACL policies available in cluster.
:param rtype: list
"""
return self._get(["policies"])

def read_policy(self, id):
"""Read an existing policy with the given ID.
:param str id: The ID of the policy.
:param rtype: dict
"""
return self._get(["policy", id])

def create_policy(self,
name,
datacenters=None,
description=None,
rules=None):
"""Create policy with name given and rules.
:param str name: name of the policy
:param list() datacenters: A list of datacenters to filter on policy.
:param str description: Human readable description of the policy.
:param str rules: A json serializable string for ACL rules.
:param rtype: dict
"""
return self._put_response_body(["policy"], {},
dict(
model.ACLPolicy(
name=name,
datacenters=datacenters,
description=description,
rules=rules)))

def update_policy(self,
id,
name,
datacenters=None,
description=None,
rules=None):
"""Update policy with id given.
:param str id: A UUID for the policy to update.
:param str name: name of the policy
:param list() datacenters: A list of datacenters to filter on policy.
:param str description: Human readable description of the policy.
:param str rules: A json serializable string for ACL rules.
:param rtype: dict
"""
return self._put_response_body(["policy", id], {},
dict(
model.ACLPolicy(
name=name,
datacenters=datacenters,
description=description,
rules=rules)))

def delete_policy(self, id):
"""Delete an existing policy with the given ID.
:param str id: The ID of the policy.
:param rtype: bool
"""
return self._delete(["policy", id])

def list_roles(self):
"""List all ACL roles available in cluster
:param rtype: list
"""
return self._get(["roles"])

def read_role(self, id=None, name=None):
"""Read an existing role with the given ID or Name.
:param str id: The ID of the role.
:param str name: The name of the role.
:param rtype: dict
"""
if id is not None:
return self._get(["role", id])
elif name is not None:
return self._get(["role", "name", name])
else:
raise exceptions.NotFound("Either id or name must be specified")

def create_role(self,
name,
description=None,
policies=None,
service_identities=None):
"""Create an ACL role from a list of policies or service identities.
:param str name: The name of the ACL role. Must be unique.
:param str description: The description of the ACL role.
:param PolicyLinks policies: An array of PolicyLink.
:param ServiceIdentities service_identities: A ServiceIdentity array.
:param rtype: dict
"""
return self._put_response_body(
["role"], {},
dict(
model.ACLRole(name=name,
description=description,
policies=policies,
service_identities=service_identities)))

def update_role(self,
id,
name,
description=None,
policies=None,
service_identities=None):
"""Update role with id given.
:param str id: A UUID for the policy to update.
:param str name: name of the policy
:param list() datacenters: A list of datacenters to filter on policy.
:param str description: Human readable description of the policy.
:param str rules: A json serializable string for ACL rules.
:param rtype: dict
"""
return self._put_response_body(
["role", id], {},
dict(
model.ACLRole(name=name,
description=description,
policies=policies,
service_identities=service_identities)))

def delete_role(self, id):
"""Delete an existing role with the given ID.
:param str id: The ID of the role.
:param rtype: bool
"""
return self._delete(["policy", id])

def list_tokens(self):
"""List all ACL tokens available in cluster.
:param rtype: list
"""
return self._get(["tokens"])

def read_token(self, accessor_id):
"""Read an existing token with the given ID.
:param str id: The ID of the role.
:param rtype: dict
"""
return self._get(["token", accessor_id])

def read_self_token(self):
"""Retrieve the currently used token.
:param rtype: dict
"""
return self._get(["token", "self"])

def create_token(self,
accessor_id=None,
description=None,
expiration_time=None,
expiration_ttl=None,
local=False,
policies=None,
roles=None,
secret_id=None,
service_identities=None):
"""Create a token from the roles, policies, and service identities
provided.
:param str accessor_id: A UUID for accessing the token.
:param str description: A human-readable description of the token.
:param str expiration_time: The amount of time till the token expires.
:param str expiration_ttl: Sets expiration_time to creation time +
expiration_ttl value.
:param bool local: Whether the token is only locally available in the
current datacenter or to all datacenters defined.
:param PolicyLinks policies: A PolicyLink array.
:param RoleLinks roles: A RoleLink array.
:param str secret_id: A UUID for making requests to consul.
:param ServiceIdentities service_identities: A ServiceIdentity array.
:param rtype: dict
"""
return self._put_response_body(
["token"], {},
dict(
model.ACLToken(accessor_id=accessor_id,
description=description,
expiration_time=expiration_time,
expiration_ttl=expiration_ttl,
local=local,
policies=policies,
roles=roles,
secret_id=secret_id,
service_identities=service_identities)))

def update_token(self,
accessor_id,
description=None,
expiration_time=None,
expiration_ttl=None,
local=False,
policies=None,
roles=None,
secret_id=None,
service_identities=None):
"""Create a token from the roles, policies, and service identities
provided.
:param str accessor_id: A UUID for accessing the token.
:param str description: A human-readable description of the token.
:param str expiration_time: The amount of time till the token expires.
:param str expiration_ttl: Sets expiration_time to creation time +
expiration_ttl value.
:param bool local: Whether the token is only locally available in the
current datacenter or to all datacenters defined.
:param PolicyLinks policies: A PolicyLink array.
:param RoleLinks roles: A RoleLink array.
:param str secret_id: A UUID for making requests to consul.
:param ServiceIdentities service_identities: A ServiceIdentity array.
:param rtype: dict
"""
return self._put_response_body(
["token", accessor_id], {},
dict(
model.ACLToken(accessor_id=accessor_id,
description=description,
expiration_time=expiration_time,
expiration_ttl=expiration_ttl,
local=local,
policies=policies,
roles=roles,
secret_id=secret_id,
service_identities=service_identities)))

def clone_token(self, accessor_id, description=None):
"""Clone a token by the accessor_id.
:param str accessor_id: A UUID for accessing the token.
:param str description: A human-readable description of the token.
:param rtype: dict
"""
return self._put_response_body(
["token", accessor_id, "clone"], {},
dict(model.ACLToken(description=description)))

def delete_token(self, accessor_id):
"""Delete an existing token with the given AcccessorID.
:param str id: The AccessorID of the token.
:param rtype: bool
"""
return self._delete(["token", accessor_id])

# NOTE: Everything below here is deprecated post consul-1.4.0.

def bootstrap(self):
"""This endpoint does a special one-time bootstrap of the ACL system,
making the first management token if the acl_master_token is not
Expand Down Expand Up @@ -69,9 +354,11 @@ def create(self, name, acl_type='client', rules=None):
:raises: consulate.exceptions.Forbidden
"""
return self._put_response_body(
['create'], {}, dict(model.ACL(
name=name, type=acl_type, rules=rules)))['ID']
return self._put_response_body(['create'], {},
dict(
model.ACL(name=name,
type=acl_type,
rules=rules)))['ID']

def clone(self, acl_id):
"""Clone an existing ACL returning the new ACL ID
Expand Down Expand Up @@ -147,6 +434,9 @@ def update(self, acl_id, name, acl_type='client', rules=None):
:raises: consulate.exceptions.Forbidden
"""
return self._put_response_body(
['update'], {}, dict(model.ACL(
id=acl_id, name=name, type=acl_type, rules=rules)))['ID']
return self._put_response_body(['update'], {},
dict(
model.ACL(id=acl_id,
name=name,
type=acl_type,
rules=rules)))['ID']
24 changes: 20 additions & 4 deletions consulate/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,28 @@ def _get(self, params, query_params=None, raise_on_404=False,
:rtype: dict or list or None
"""
response = self._adapter.get(
self._build_uri(params, query_params), timeout=timeout)
response = self._adapter.get(self._build_uri(params, query_params),
timeout=timeout)
if utils.response_ok(response, raise_on_404):
return response.body
return []

def _delete(
self,
params,
raise_on_404=False,
):
"""Perform a DELETE request
:param list params: List of path parts
:rtype: bool
"""
response = self._adapter.delete(self._build_uri(params))
if utils.response_ok(response, raise_on_404):
return response.body
return False

def _get_list(self, params, query_params=None):
"""Return a list queried from Consul
Expand Down Expand Up @@ -105,8 +121,8 @@ def _put_no_response_body(self, url_parts, query=None, payload=None):
self._adapter.put(self._build_uri(url_parts, query), payload))

def _put_response_body(self, url_parts, query=None, payload=None):
response = self._adapter.put(
self._build_uri(url_parts, query), data=payload)
response = self._adapter.put(self._build_uri(url_parts, query),
data=payload)
if utils.response_ok(response):
return response.body

Expand Down
Loading

0 comments on commit 39e6c17

Please sign in to comment.