sym-cli
Advanced tools
| import os | ||
| from configparser import ConfigParser | ||
| from functools import cached_property | ||
| from pathlib import Path | ||
| from typing import Iterator, Tuple | ||
| from boto3 import setup_default_session | ||
| from sym.shared.cli.helpers.contexts import push_env | ||
| from sym.shared.cli.helpers.keywords_to_options import Argument | ||
| from sym.cli.helpers.boto import get_identity | ||
| from ..decorators import command_require_bins, intercept_errors, run_subprocess | ||
| from ..errors import InvalidResource | ||
| from ..helpers.params import Profile | ||
| from .saml_client import SAMLClient | ||
| # The docs say that the credentials file is for sensitive values like actual access keys etc | ||
| # and the config file for less sensitive things like role names, SSO configs. | ||
| AwsConfigPath = Path(os.getenv("AWS_CONFIG_FILE", Path.home() / ".aws" / "config")) | ||
| class AwsConfig(SAMLClient): | ||
| binary = "aws" | ||
| option_value = "aws-config" | ||
| priority = 0 | ||
| setup_help = f"Set up your profile in `{str(AwsConfigPath)}`." | ||
| resource: str | ||
| options: "GlobalOptions" | ||
| def __init__(self, resource: str, *, options: "GlobalOptions") -> None: | ||
| super().__init__(resource, options=options) | ||
| # Make the default session use our AWS profile so we don't need to manage sessions in | ||
| # whatever other call chains there are to get AWS creds | ||
| setup_default_session(profile_name=resource) | ||
| @classmethod | ||
| def _read_creds_config(cls): | ||
| config = ConfigParser(strict=False) | ||
| if AwsConfigPath.exists(): | ||
| config.read(AwsConfigPath) | ||
| return config | ||
| @classmethod | ||
| def validate_resource(cls, resource: str): | ||
| config = cls._read_creds_config() | ||
| return config.has_section(cls._profile_name(resource)) | ||
| @cached_property | ||
| def _section(self): | ||
| config = self.__class__._read_creds_config() | ||
| return config[self.__class__._profile_name(self.resource)] | ||
| @classmethod | ||
| def _profile_name(cls, resource: str): | ||
| return f"profile {resource}" | ||
| def raise_if_invalid(self): | ||
| if self.__class__.validate_resource(self.resource): | ||
| return | ||
| raise InvalidResource( | ||
| self.resource, self.__class__._read_creds_config().sections() | ||
| ) | ||
| # Returning an empty dict here because we set up a default boto session above, so no need | ||
| # for creds here | ||
| def get_creds(self): | ||
| return {} | ||
| @intercept_errors() | ||
| @run_subprocess | ||
| @command_require_bins(binary) | ||
| def _exec(self, *args: str, **opts: str) -> Iterator[Tuple[Argument, ...]]: | ||
| with push_env("AWS_PROFILE", self.resource): | ||
| yield (*args, opts) | ||
| def is_setup(self) -> bool: | ||
| return AwsConfigPath.exists() | ||
| def _ensure_config(self, profile: Profile) -> ConfigParser: | ||
| return ConfigParser(strict=False) | ||
| def _ensure_session(self, *, force: bool): | ||
| if not force and not self._creds_expiring(): | ||
| return | ||
| get_identity(self) | ||
| def get_profile(self): | ||
| return Profile( | ||
| display_name=self.resource, | ||
| region=self._section.get("region"), | ||
| arn=self._section.get("x_principal_arn"), | ||
| ansible_bucket=self._section.get("x_sym_ansible_bucket"), | ||
| ) | ||
| def send_analytics_event(self): | ||
| pass |
+4
-2
| Metadata-Version: 2.1 | ||
| Name: sym-cli | ||
| Version: 0.4.11 | ||
| Version: 0.5.0 | ||
| Summary: Sym's Official CLI for Users | ||
@@ -11,5 +11,7 @@ Home-page: https://symops.com/ | ||
| Classifier: Programming Language :: Python :: 3 | ||
| Classifier: Programming Language :: Python :: 3.10 | ||
| Classifier: Programming Language :: Python :: 3.8 | ||
| Classifier: Programming Language :: Python :: 3.9 | ||
| Classifier: Programming Language :: Python :: 3.10 | ||
| Classifier: Programming Language :: Python :: 3.11 | ||
| Classifier: Programming Language :: Python :: 3 | ||
| Requires-Dist: PyYAML (>=5.3.1,<6.0.0) | ||
@@ -16,0 +18,0 @@ Requires-Dist: SecretStorage (>=3.2.0,<4.0.0) |
+1
-1
| [tool.poetry] | ||
| name = "sym-cli" | ||
| version = "0.4.11" | ||
| version = "0.5.0" | ||
| description = "Sym's Official CLI for Users" | ||
@@ -5,0 +5,0 @@ authors = ["SymOps, Inc. <pypi@symops.io>"] |
@@ -35,9 +35,12 @@ import json | ||
| creds = saml_client.get_creds() | ||
| return boto3.client( | ||
| service, | ||
| config=BotoConfig(region_name=get_region(saml_client, creds)), | ||
| aws_access_key_id=creds["AWS_ACCESS_KEY_ID"], | ||
| aws_secret_access_key=creds["AWS_SECRET_ACCESS_KEY"], | ||
| aws_session_token=creds.get("AWS_SESSION_TOKEN"), | ||
| ) | ||
| if access_key_id := creds.get("AWS_ACCESS_KEY_ID"): | ||
| return boto3.client( | ||
| service, | ||
| config=BotoConfig(region_name=get_region(saml_client, creds)), | ||
| aws_access_key_id=access_key_id, | ||
| aws_secret_access_key=creds["AWS_SECRET_ACCESS_KEY"], | ||
| aws_session_token=creds.get("AWS_SESSION_TOKEN"), | ||
| ) | ||
| # If there is no access key id, then assume that the boto3 default session is set up | ||
| return boto3.client(service) | ||
@@ -44,0 +47,0 @@ |
@@ -184,23 +184,2 @@ from typing import Dict, List, NamedTuple, Optional, Tuple, TypedDict | ||
| }, | ||
| "healthy-health": { | ||
| "resource_env_var": "ENVIRONMENT", | ||
| "users": {"ssh": "ubuntu"}, | ||
| "domain": "healthy-health.co", | ||
| "aws_saml_url": ( | ||
| "https://healthy-health.okta.com/home/amazon_aws/0oagrj7yFaVtJoI2N5d5/272" | ||
| ), | ||
| "aws_okta_params": { | ||
| "mfa_provider": "OKTA", | ||
| "assume_role_ttl": "1h", | ||
| "session_ttl": "30m", | ||
| }, | ||
| "saml2aws_params": {"mfa": "Auto", "aws_session_duration": "1800"}, | ||
| "profiles": { | ||
| "prod": Profile( | ||
| display_name="Prod", | ||
| region="us-east-1", | ||
| arn="arn:aws:iam::223440862848:role/ssm-healthy-health-user-prod", | ||
| ), | ||
| }, | ||
| }, | ||
| } | ||
@@ -207,0 +186,0 @@ |
@@ -21,3 +21,5 @@ import os | ||
| # This client assumes that access key and secret are defined in the credentials file. | ||
| # If you want to use a named profile that works with SSO or some other supported AWS credential | ||
| # process, use AwsConfig | ||
| class AwsProfile(SAMLClient): | ||
@@ -24,0 +26,0 @@ binary = "aws" |
@@ -10,4 +10,4 @@ from typing import Literal, Optional, Type | ||
| SAMLClientName = Literal["auto", "aws-okta", "saml2aws", "aws-profile"] | ||
| AUTO_EXCLUDED_SAML_CLIENT_NAMES = ["aws-profile"] | ||
| SAMLClientName = Literal["auto", "aws-okta", "saml2aws", "aws-profile", "aws-config"] | ||
| AUTO_EXCLUDED_SAML_CLIENT_NAMES = ["aws-profile", "aws-config"] | ||
@@ -14,0 +14,0 @@ |
@@ -36,3 +36,3 @@ import socket | ||
| regions = ec2_client.get_regions() | ||
| assert len(regions) == 26 | ||
| assert len(regions) == 27 | ||
| assert "us-east-1" in regions | ||
@@ -39,0 +39,0 @@ |
@@ -1,1 +0,1 @@ | ||
| __version__ = '0.4.11' | ||
| __version__ = '0.5.0' |
-70
| # -*- coding: utf-8 -*- | ||
| from setuptools import setup | ||
| packages = \ | ||
| ['cli', | ||
| 'cli.actions', | ||
| 'cli.ansible', | ||
| 'cli.ansible.connection', | ||
| 'cli.commands', | ||
| 'cli.constants', | ||
| 'cli.data', | ||
| 'cli.helpers', | ||
| 'cli.helpers.check', | ||
| 'cli.helpers.ec2', | ||
| 'cli.saml_clients', | ||
| 'cli.tests', | ||
| 'cli.tests.commands', | ||
| 'cli.tests.decorators', | ||
| 'cli.tests.helpers', | ||
| 'cli.tests.helpers.ec2', | ||
| 'cli.tests.helpers.updater', | ||
| 'cli.tests.integration', | ||
| 'cli.tests.saml_clients'] | ||
| package_data = \ | ||
| {'': ['*'], 'cli.tests.helpers.updater': ['responses/*']} | ||
| install_requires = \ | ||
| ['PyYAML>=5.3.1,<6.0.0', | ||
| 'SecretStorage>=3.2.0,<4.0.0', | ||
| 'analytics-python>=1.3.1,<2.0.0', | ||
| 'boto3>=1.16.20,<2.0.0', | ||
| 'click-option-group>=0.5.1,<0.6.0', | ||
| 'click>=8.0.0,<9.0.0', | ||
| 'colorama<0.4.4', | ||
| 'cryptography==3.4.8', | ||
| 'immutables>=0.14,<0.15', | ||
| 'keyring>=21.5.0,<22.0.0', | ||
| 'mistune<2.0.0', | ||
| 'policyuniverse>=1.3.2,<2.0.0', | ||
| 'portalocker>=2.0.0,<3.0.0', | ||
| 'python-dateutil>=2.8.1,<3.0.0', | ||
| 'requests>=2.25,<3.0', | ||
| 'semver>=2.13.0,<3.0.0', | ||
| 'sentry-sdk>=0.19.3,<0.20.0', | ||
| 'sym-shared-cli>=0.2.3,<0.3.0', | ||
| 'validators>=0.18.1,<0.19.0'] | ||
| entry_points = \ | ||
| {'console_scripts': ['sym = sym.cli.sym:sym']} | ||
| setup_kwargs = { | ||
| 'name': 'sym-cli', | ||
| 'version': '0.4.11', | ||
| 'description': "Sym's Official CLI for Users", | ||
| 'long_description': '# sym-cli\n\nThis is the official CLI for [Sym](https://symops.com/) Users. Check out the docs [here](https://docs.symops.com/docs/install-sym-cli).\n', | ||
| 'author': 'SymOps, Inc.', | ||
| 'author_email': 'pypi@symops.io', | ||
| 'maintainer': None, | ||
| 'maintainer_email': None, | ||
| 'url': 'https://symops.com/', | ||
| 'packages': packages, | ||
| 'package_data': package_data, | ||
| 'install_requires': install_requires, | ||
| 'entry_points': entry_points, | ||
| 'python_requires': '>=3.8,<4.0', | ||
| } | ||
| setup(**setup_kwargs) |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
831271
0.15%