Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Flag support. (Implementation 2) #30

Merged
merged 17 commits into from
Apr 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ AWS:
- rate limit handling, with exponential backoff.
- multi-account sts:assumerole abstraction.
- orchestrates all the calls required to fully describe an item.
- control which attributes are returned with flags.

GCP:
- choosing the best client based on service
- client caching
- general caching and stats decorators available
- basic support for non-specified discovery-API services
- control which attributes are returned with flags.

## Orchestration Supported Technologies

Expand Down Expand Up @@ -129,7 +131,7 @@ GCP:

### AWS IAM Role

from cloudaux.orchestration.aws.iam.role import get_role
from cloudaux.orchestration.aws.iam.role import get_role, FLAGS

# account_number may be extracted from the ARN of the role passed to get_role
# if not included in conn.
Expand All @@ -142,8 +144,15 @@ GCP:
role = get_role(
dict(arn='arn:aws:iam::000000000000:role/myRole', role_name='myRole'),
output='camelized', # optional: {camelized underscored}
flags=FLAGS.ALL, # optional
**conn)

# The flags parameter is optional but allows the user to indicate that
# only a subset of the full item description is required.
# IAM Role Flag Options:
# BASE, MANAGED_POLICIES, INLINE_POLICIES, INSTANCE_PROFILES, ALL (default)
# For instance: flags=FLAGS.MANAGED_POLICIES | FLAGS.INSTANCE_PROFILES

# cloudaux makes a number of calls to obtain a full description of the role
print(json.dumps(role, indent=4, sort_keys=True))

Expand All @@ -162,11 +171,13 @@ GCP:

### GCP IAM Service Account

from cloudaux.orchestration.gcp.iam.serviceaccount import get_serviceaccount_complete
from cloudaux.orchestration.gcp.iam.serviceaccount import get_serviceaccount_complete, FLAGS
sa_name = 'projects/my-project-one/serviceAccounts/service-account-key@my-project-one.iam.gserviceaccount.com'
sa = get_serviceaccount_complete(sa_name, **conn_details)
sa = get_serviceaccount_complete(sa_name, flags=FLAGS.ALL, **conn_details)
print(json.dumps(sa, indent=4, sort_keys=True))

# Flag options for Service Accounts are BASE, KEYS, POLICY, ALL (default).

{
"DisplayName": "service-account",
"Email": "service-account@my-project-one.iam.gserviceaccount.com",
Expand Down
2 changes: 1 addition & 1 deletion cloudaux/__about__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
__summary__ = 'Cloud Auxiliary is a python wrapper and orchestration module for interacting with cloud providers'
__uri__ = 'https://github.com/Netflix-Skunkworks/cloudaux'

__version__ = '1.1.9'
__version__ = '1.2.0'

__author__ = 'Patrick Kelley'
__email__ = 'patrick@netflix.com'
Expand Down
32 changes: 28 additions & 4 deletions cloudaux/aws/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Cloud Auxiliary has support for Amazon Web Services.
- rate limit handling, with exponential backoff.
- multi-account sts:assumerole abstraction.
- orchestrates all the calls required to fully describe an item.
- control which attributes are returned flags.

## Orchestration Supported Technologies

Expand Down Expand Up @@ -72,7 +73,7 @@ Cloud Auxiliary has support for Amazon Web Services.

### Role

from cloudaux.orchestration.aws.iam.role import get_role
from cloudaux.orchestration.aws.iam.role import get_role, FLAGS

# account_number may be extracted from the ARN of the role passed to get_role
# if not included in conn.
Expand All @@ -85,7 +86,14 @@ Cloud Auxiliary has support for Amazon Web Services.
role = get_role(
dict(arn='arn:aws:iam::000000000000:role/myRole', role_name='myRole'),
output='camelized', # optional: {camelized underscored}
flags=FLAGS.ALL, # optional
**conn)

# The flags parameter is optional but allows the user to indicate that
# only a subset of the full item description is required.
# IAM Role Flag Options:
# BASE, MANAGED_POLICIES, INLINE_POLICIES, INSTANCE_PROFILES, ALL (default)
# For instance: flags=FLAGS.MANAGED_POLICIES | FLAGS.INSTANCE_PROFILES

# cloudaux makes a number of calls to obtain a full description of the role
print(json.dumps(role, indent=4, sort_keys=True))
Expand All @@ -105,11 +113,19 @@ Cloud Auxiliary has support for Amazon Web Services.

### User

from cloudaux.orchestration.aws.iam.user import get_user
from cloudaux.orchestration.aws.iam.user import get_user, FLAGS

user = get_user(
dict(arn='arn:aws:iam::000000000000:user/myUser', role_name='myUser'),
flags=FLAGS.ALL,
**conn)

# The flags parameter is optional but allows the user to indicate that
# only a subset of the full item description is required.
# IAM User Flag Options:
# BASE, ACCESS_KEYS, INLINE_POLICIES, MANAGED_POLICIES
# MFA_DEVICES, LOGIN_PROFILE, SIGNING_CERTIFICATES, ALL (default)
# For instance: flags=FLAGS.ACCESS_KEYS | FLAGS.MFA_DEVICES | FLAGS.LOGIN_PROFILE

print(json.dumps(user, indent=2, sort_keys=True))

Expand Down Expand Up @@ -141,13 +157,21 @@ Cloud Auxiliary has support for Amazon Web Services.

### S3

from cloudaux.orchestration.aws.s3 import get_bucket
from cloudaux.orchestration.aws.s3 import get_bucket, FLAGS

conn = dict(
account_number='000000000000',
assume_role='SecurityMonkey')

bucket = get_bucket('MyS3Bucket', **conn)
bucket = get_bucket('MyS3Bucket', flags=FLAGS.ALL, **conn)

# The flags parameter is optional but allows the user to indicate that
# only a subset of the full item description is required.
# S3 Flag Options are:
# BASE, GRANTS, GRANT_REFERENCES, OWNER, LIFECYCLE, LOGGING, POLICY, TAGS
# VERSIONING, WEBSITE, CORS, NOTIFICATIONS, ACCELERATION, REPLICATION
# ANALYTICS, METRICS, INVENTORY, CREATED_DATE, ALL (default)
# For instance: flags=FLAGS.WEBSITE | FLAGS.CORS | FLAGS.POLICY

print(json.dumps(bucket, indent=2, sort_keys=True))

Expand Down
13 changes: 11 additions & 2 deletions cloudaux/gcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Cloud Auxiliary has support for Google Cloud Platform.
- client caching
- general caching and stats decorators available
- basic support for non-specified discovery-API services
- control which attributes are returned with flags.

## Orchestration Supported Technologies

Expand Down Expand Up @@ -66,10 +67,12 @@ Cloud Auxiliary has support for Google Cloud Platform.

### IAM Service Account

from cloudaux.orchestration.gcp.iam.serviceaccount import get_serviceaccount_complete
from cloudaux.orchestration.gcp.iam.serviceaccount import get_serviceaccount_complete, FLAGS
sa_name = 'projects/my-project-one/serviceAccounts/service-account-key@my-project-one.iam.gserviceaccount.com'
sa = get_serviceaccount_complete(sa_name, **conn_details)
sa = get_serviceaccount_complete(sa_name, flags=FLAGS.ALL, **conn_details)
print(json.dumps(sa, indent=4, sort_keys=True))

# Flag options for Service Accounts are BASE, KEYS, POLICY, ALL (default).

{
"DisplayName": "service-account",
Expand Down Expand Up @@ -103,6 +106,9 @@ Cloud Auxiliary has support for Google Cloud Platform.
net_subnet = get_network_and_subnetworks(network=NETWORK, **conn_details)
print(json.dumps(net_subnet, indent=4, sort_keys=True))

# Flag options for Service Accounts are BASE, ALL (default).
# BASE and ALL are equivelant for this service.

{
"AutoCreateSubnetworks": true,
"CreationTimestamp": "2016-05-09T11:15:47.434-07:00",
Expand Down Expand Up @@ -132,6 +138,9 @@ Cloud Auxiliary has support for Google Cloud Platform.
b = get_bucket(bucket_name=BUCKET, **conn_details)
print(json.dumps(b, indent=4, sort_keys=True))

# Flag options for Service Accounts are BASE, ALL (default).
# BASE and ALL are equivelant for this service.

{
"Acl": [
{
Expand Down
40 changes: 29 additions & 11 deletions cloudaux/orchestration/aws/iam/role.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,33 @@
from cloudaux.aws.iam import get_role_managed_policies, get_role_inline_policies, get_role_instance_profiles
from cloudaux.orchestration.aws import _get_name_from_structure, _conn_from_args
from cloudaux.orchestration import modify
from cloudaux.orchestration.flag_registry import FlagRegistry, Flags


class RoleFlagRegistry(FlagRegistry):
from collections import defaultdict
r = defaultdict(list)


FLAGS = Flags('BASE', 'MANAGED_POLICIES', 'INLINE_POLICIES', 'INSTANCE_PROFILES')


@RoleFlagRegistry.register(flag=FLAGS.MANAGED_POLICIES, key='managed_policies')
def get_managed_policies(role, **conn):
return get_role_managed_policies(role, **conn)


@RoleFlagRegistry.register(flag=FLAGS.INLINE_POLICIES, key='inline_policies')
def get_inline_policies(role, **conn):
return get_role_inline_policies(role, **conn)


@RoleFlagRegistry.register(flag=FLAGS.INSTANCE_PROFILES, key='instance_profiles')
def get_instance_profiles(role, **conn):
return get_role_instance_profiles(role, **conn)


@RoleFlagRegistry.register(flag=FLAGS.BASE)
def _get_base(role, **conn):
"""
Determine whether the boto get_role call needs to be made or if we already have all that data
Expand All @@ -27,11 +52,12 @@ def _get_base(role, **conn):

# cast CreateDate from a datetime to something JSON serializable.
role.update(dict(CreateDate=str(role['CreateDate'])))
role['_version'] = 1

return role


def get_role(role, output='camelized', **conn):
def get_role(role, output='camelized', flags=FLAGS.ALL, **conn):
"""
Orchestrates all the calls required to fully build out an IAM Role in the following format:

Expand All @@ -55,13 +81,5 @@ def get_role(role, output='camelized', **conn):
"""
role = modify(role, 'camelized')
_conn_from_args(role, conn)
role = _get_base(role, **conn)
role.update(
{
'managed_policies': get_role_managed_policies(role, **conn),
'inline_policies': get_role_inline_policies(role, **conn),
'instance_profiles': get_role_instance_profiles(role, **conn),
'_version': 1
}
)
return modify(role, format=output)
RoleFlagRegistry.build_out(role, flags, role, **conn)
return modify(role, format=output)
56 changes: 43 additions & 13 deletions cloudaux/orchestration/aws/iam/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,48 @@
from cloudaux.aws.iam import get_user_signing_certificates
from cloudaux.orchestration.aws import _get_name_from_structure, _conn_from_args
from cloudaux.orchestration import modify
from cloudaux.orchestration.flag_registry import FlagRegistry, Flags


class UserFlagRegistry(FlagRegistry):
from collections import defaultdict
r = defaultdict(list)


FLAGS = Flags('BASE', 'ACCESS_KEYS', 'INLINE_POLICIES', 'MANAGED_POLICIES', 'MFA_DEVICES', 'LOGIN_PROFILE', 'SIGNING_CERTIFICATES')


@UserFlagRegistry.register(flag=FLAGS.ACCESS_KEYS, key='access_keys')
def get_access_keys(user, **conn):
return get_user_access_keys(user, **conn)


@UserFlagRegistry.register(flag=FLAGS.INLINE_POLICIES, key='inline_policies')
def get_inline_policies(user, **conn):
return get_user_inline_policies(user, **conn)


@UserFlagRegistry.register(flag=FLAGS.MANAGED_POLICIES, key='managed_policies')
def get_managed_policies(user, **conn):
return get_user_managed_policies(user, **conn)


@UserFlagRegistry.register(flag=FLAGS.MFA_DEVICES, key='mfa_devices')
def get_mfa_devices(user, **conn):
return get_user_mfa_devices(user, **conn)


@UserFlagRegistry.register(flag=FLAGS.LOGIN_PROFILE, key='login_profile')
def get_login_profile(user, **conn):
return get_user_login_profile(user, **conn)


@UserFlagRegistry.register(flag=FLAGS.SIGNING_CERTIFICATES, key='signing_certificates')
def get_signing_certificates(user, **conn):
return get_user_signing_certificates(user, **conn)


@UserFlagRegistry.register(flag=FLAGS.BASE)
def _get_base(user, **conn):
base_fields = frozenset(['Arn', 'CreateDate', 'Path', 'UserId', 'UserName'])
needs_base = False
Expand All @@ -27,10 +67,11 @@ def _get_base(user, **conn):
if 'PasswordLastUsed' in user:
user.update(dict(PasswordLastUsed=str(user['PasswordLastUsed'])))

user['_version'] = 1
return user


def get_user(user, output='camelized', **conn):
def get_user(user, output='camelized', flags=FLAGS.ALL, **conn):
"""
Orchestrates all the calls required to fully build out an IAM User in the following format:

Expand All @@ -55,16 +96,5 @@ def get_user(user, output='camelized', **conn):
"""
user = modify(user, 'camelized')
_conn_from_args(user, conn)
user = _get_base(user, **conn)
user.update(
{
'access_keys': get_user_access_keys(user, **conn),
'inline_policies': get_user_inline_policies(user, **conn),
'managed_policies': get_user_managed_policies(user, **conn),
'mfa_devices': get_user_mfa_devices(user, **conn),
'login_profile': get_user_login_profile(user, **conn),
'signing_certificates': get_user_signing_certificates(user, **conn),
'_version': 1
}
)
UserFlagRegistry.build_out(user, flags, user, **conn)
return modify(user, format=output)
Loading