Skip to content

Commit

Permalink
v2 API Design (Netflix#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
patricksanders authored May 18, 2020
1 parent b19de2e commit 97db5a0
Show file tree
Hide file tree
Showing 10 changed files with 709 additions and 0 deletions.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ It is possible to use Docker `docker-compose-test.yaml` to run ConsoleMe and its
in Docker with the default plugin set. Configure a new Docker Python interpreter to run __main__.py with your
working directory set to `/apps/consoleme` (on the container). This flow was tested on Windows 10.

### Generating Models from Swagger Spec

When changes are made to the Swagger spec, models may need to be regenerated using [datamodel-code-generator](https://github.com/koxudaxi/datamodel-code-generator).

```bash
pip install datamodel-code-generator
datamodel-codegen --input swagger.yaml --output consoleme/models/models.py
```

## Generate an AMI to deploy ConsoleMe to EC2

Expand Down
Empty file added consoleme/models/__init__.py
Empty file.
127 changes: 127 additions & 0 deletions consoleme/models/base_models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# generated by datamodel-codegen:
# filename: swagger.yaml
# timestamp: 2020-05-14T17:32:50+00:00

from __future__ import annotations

from datetime import datetime
from enum import Enum
from typing import Any, Dict, List, Optional

from pydantic import BaseModel, Field, constr


class ResourceModel(BaseModel):
arn: str = Field(..., description='resource ARN')
account_id: str = Field(..., description='AWS account ID')
account_name: str = Field(..., description='human-friendly AWS account name')
policy_sha256: str = Field(
..., description='hash of the most recent resource policy seen by ConsoleMe'
)
policy: str
owner: str = Field(
..., description='email address of team or individual who owns this resource'
)
approvers: List[str]
resource_type: str
last_updated: datetime = Field(
..., description='last time resource was updated from source-of-truth'
)


class RequestModel(BaseModel):
id: str
arn: str = Field(..., description='ARN of principal being modified')
timestamp: datetime
justification: str
requester_email: str
approvers: List[str] = Field(
...,
description='list of approvers, derived from approvers of `resource`s in `changes`',
)
status: str


class ChangeType(Enum):
inline_policy = 'inline_policy'
managed_policy = 'managed_policy'
resource_policy = 'resource_policy'


class ChangeModel(BaseModel):
change_type: ChangeType
resource: ResourceModel


class Action(Enum):
attach = 'attach'
detach = 'detach'


class ManagedPolicyChangeModel(ChangeModel):
arn: str
policy_name: str
action: Action


class PolicyModel(BaseModel):
policy_document: str = Field(..., description='JSON policy document')
policy_sha256: str = Field(..., description='hash of policy_document')


class RoleModel(BaseModel):
name: str
account_id: Optional[constr(min_length=12, max_length=12)] = None
account_name: Optional[str] = None
arn: Optional[str] = None


class ExtendedRoleModel(RoleModel):
inline_policies: List[Dict[str, Any]]
assume_role_policies: List[Dict[str, Any]]
managed_policies: List[Dict[str, Any]]
tags: List[Dict[str, Any]]
templated: Optional[bool] = None
template_link: Optional[str] = None


class UserModel(BaseModel):
email: Optional[str] = None
extended_info: Optional[Dict[str, Any]] = None


class InlinePolicyChangeModel(ChangeModel):
arn: str
additional_arns: Optional[str] = Field(
None,
description='additional ARNs relevant to request, e.g. S3 bucket ARN with path prefix',
)
policy_name: str
new: bool
policy: PolicyModel
old_policy: Optional[PolicyModel] = None


class ResourcePolicyChangeModel(ChangeModel):
arn: str
policy: PolicyModel
old_policy: Optional[PolicyModel] = None


class CommentModel(BaseModel):
id: str
timestamp: datetime
edited: Optional[bool] = None
last_modified: Optional[datetime] = None
user_email: str
user: Optional[UserModel] = None
text: str


class ExtendedRequestModel(RequestModel):
changes: List[
InlinePolicyChangeModel, ManagedPolicyChangeModel, ResourcePolicyChangeModel
]
requester_info: UserModel
reviewer: Optional[str] = None
comments: Optional[CommentModel] = None
28 changes: 28 additions & 0 deletions consoleme/models/change.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from consoleme.models.base_models import ChangeModel
from consoleme.models.base_models import InlinePolicyChangeModel
from consoleme.models.base_models import ManagedPolicyChangeModel
from consoleme.models.base_models import ResourcePolicyChangeModel


class Change(ChangeModel):
def __init__(self, *args, **kwargs):
super().__init__(self)

def store(self):
"""save to dynamodb"""
pass


class InlinePolicyChange(InlinePolicyChangeModel):
def __init__(self, *args, **kwargs):
super().__init__(self)


class ManagedPolicyChange(ManagedPolicyChangeModel):
def __init__(self, *args, **kwargs):
super().__init__(self)


class ResourcePolicyChange(ResourcePolicyChangeModel):
def __init__(self, *args, **kwargs):
super().__init__(self)
6 changes: 6 additions & 0 deletions consoleme/models/policy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from consoleme.models.base_models import PolicyModel


class Policy(PolicyModel):
def __init__(self, *args, **kwargs):
super().__init__(self)
18 changes: 18 additions & 0 deletions consoleme/models/request.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
from consoleme.models.base_models import CommentModel
from consoleme.models.base_models import ExtendedRequestModel
from consoleme.models.base_models import RequestModel


# Putting Comment here since it is only used in the context of Requests
class Comment(CommentModel):
def __init__(self, *args, **kwargs):
super().__init__(self)


class Request(ExtendedRequestModel):
def __init__(self, *args, **kwargs):
super().__init__(self)

def store(self, dynamodb_client):
"""save to dynamodb"""
pass
6 changes: 6 additions & 0 deletions consoleme/models/resource.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from consoleme.models.models import ResourceModel


class Resource(ResourceModel):
def __init__(self, *args, **kwargs):
super().__init__(self)
7 changes: 7 additions & 0 deletions consoleme/models/role.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from consoleme.models.base_models import ExtendedRoleModel
from consoleme.models.base_models import RoleModel


class Role(ExtendedRoleModel):
def __init__(self, *args, **kwargs):
super().__init__(self)
6 changes: 6 additions & 0 deletions consoleme/models/user.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from consoleme.models.models import UserModel


class User(UserModel):
def __init__(self, *args, **kwargs):
super().__init__(self)
Loading

0 comments on commit 97db5a0

Please sign in to comment.