Skip to content

YaleSpinup/ecr-api

Repository files navigation

ecr-api

This API provides simple restful API access to a service.

Endpoints

GET /v1/ecr/ping
GET /v1/ecr/version
GET /v1/ecr/metrics

GET    /v1/ecr/{account}/repositories
POST   /v1/ecr/{account}/repositories/{group}
GET    /v1/ecr/{account}/repositories/{group}
GET    /v1/ecr/{account}/repositories/{group}/{name}
PUT    /v1/ecr/{account}/repositories/{group}/{name}
DELETE /v1/ecr/{account}/repositories/{group}/{name}

GET    /v1/ecr/{account}/repositories/{group}/{name}/images
GET    /v1/ecr/{account}/repositories/{group}/{name}/images/{tag}
DELETE /v1/ecr/{account}/repositories/{group}/{name}/images/{tag}

GET    /v1/ecr/{account}/repositories/{group}/{name}/users
POST   /v1/ecr/{account}/repositories/{group}/{name}/users
GET    /v1/ecr/{account}/repositories/{group}/{name}/users/{user}
PUT    /v1/ecr/{account}/repositories/{group}/{name}/users/{user}
DELETE /v1/ecr/{account}/repositories/{group}/{name}/users/{user}

Authentication

Authentication is accomplished via an encrypted pre-shared key passed via the X-Auth-Token header.

Usage

Repositories

Create a repository

POST /v1/ecr/{account}/repositories/{group}

Response Code Definition
200 OK create a repository
400 Bad Request badly formed request
404 Not Found account not found
500 Internal Server Error a server error occurred
Example create request body
{
    "RepositoryName": "myAwesomeRepository",
    "Groups": ["spindev-000001", "spindev-000002"],
    "ScanOnPush": "true",
    "Tags": [
        {
            "Key": "CreatedBy",
            "Value": "cf322"
        },
        {
            "Key": "spinup:spaceid",
            "Value": "spincool-00001"
        }
    ]
}
Example create response body
{
    "CreatedAt": "2020-12-14T15:34:18Z",
    "EncryptionType": "AES256",
    "Groups": ["spindev-000001", "spindev-000002"],
    "KmsKeyId": "",
    "ScanOnPush": "true",
    "ImageTagMutability": "MUTABLE",
    "RegistryId": "0123456789",
    "RepositoryArn": "arn:aws:ecr:us-east-1:0123456789:repository/spindev-00001/myAwesomeRepository",
    "RepositoryName": "spindev-00001/camdenstestrepo02",
    "RepositoryUri": "0123456789.dkr.ecr.us-east-1.amazonaws.com/spindev-00001/myAwesomeRepository",
    "Tags": [
        {
            "Key": "spinup:spaceid",
            "Value": "spindev-00001"
        },
        {
            "Key": "CreatedBy",
            "Value": "santa"
        },
        {
            "Key": "spinup:org",
            "Value": "spindev"
        },
        {
            "Key": "Name",
            "Value": "spindev-00001/myAwesomeRepository"
        }
    ]
}

List Repositories

GET /v1/ecr/{account}/repositories

Response Code Definition
200 OK return the list of repositories
400 Bad Request badly formed request
404 Not Found account not found
500 Internal Server Error a server error occurred

Example list response

[
    "spindev-00001/dasher",
    "spindev-00001/dancer",
    "spindev-00002/prancer",
    "spindev-00002/vixen"
    "spindev-00003/comet",
    "spindev-00003/cupid",
    "spindev-00004/donner",
    "spindev-00005/blitzen",
    "spindev-00006/rudolph",
]

List Repositories by group id

GET /v1/ecr/{account}/repositories/{group}

Response Code Definition
200 OK return the list of repositories
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account not found
500 Internal Server Error a server error occurred
Example list by group response
[
    "spindev-00006/rudolph"
]

Get details about a Repository

GET /v1/ecr/{account}/repositories/{group}/{id}

Response Code Definition
200 OK return details of a repository
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account or repository not found
500 Internal Server Error a server error occurred
Example show response
{
    "CreatedAt": "2020-12-14T15:34:18Z",
    "EncryptionType": "AES256",
    "Groups": ["spindev-000001", "spindev-000002"],
    "KmsKeyId": "",
    "ScanOnPush": "true",
    "ImageTagMutability": "MUTABLE",
    "RegistryId": "0123456789",
    "RepositoryArn": "arn:aws:ecr:us-east-1:0123456789:repository/spindev-00001/myAwesomeRepository",
    "RepositoryName": "spindev-00001/camdenstestrepo02",
    "RepositoryUri": "0123456789.dkr.ecr.us-east-1.amazonaws.com/spindev-00001/myAwesomeRepository",
    "Tags": [
        {
            "Key": "spinup:spaceid",
            "Value": "spindev-00001"
        },
        {
            "Key": "CreatedBy",
            "Value": "santa"
        },
        {
            "Key": "spinup:org",
            "Value": "spindev"
        },
        {
            "Key": "Name",
            "Value": "spindev-00001/myAwesomeRepository"
        }
    ]
}

Update a repository

PUT /1/ecr/{account}/repositories/{group}/{id}

Example update request body
{
    "ScanOnPush": "false",
    "Groups": ["spindev-000001", "spindev-000002", "spindev-000003"],
    "Tags": [
        {
            "Key": "Application",
            "Value": "MyAwesomeCloudApp"
        }
    ]
}
Example update response body
{
    "CreatedAt": "2020-12-14T15:34:18Z",
    "EncryptionType": "AES256",
    "Groups": ["spindev-000001", "spindev-000002", "spindev-000003"],
    "KmsKeyId": "",
    "ScanOnPush": "false",
    "ImageTagMutability": "MUTABLE",
    "RegistryId": "0123456789",
    "RepositoryArn": "arn:aws:ecr:us-east-1:0123456789:repository/spindev-00001/myAwesomeRepository",
    "RepositoryName": "spindev-00001/camdenstestrepo02",
    "RepositoryUri": "0123456789.dkr.ecr.us-east-1.amazonaws.com/spindev-00001/myAwesomeRepository",
    "Tags": [
        {
            "Key": "spinup:spaceid",
            "Value": "spindev-00001"
        },
        {
            "Key": "CreatedBy",
            "Value": "santa"
        },
        {
            "Key": "spinup:org",
            "Value": "spindev"
        },
        {
            "Key": "Name",
            "Value": "spindev-00001/myAwesomeRepository"
        },
        {
            "Key": "Application",
            "Value": "MyAwesomeCloudApp"
        }
    ]
}

Delete a repository and all images

NOTE: deleting a repository does not currently cleanup users, this must be done first.

DELETE /v1/ecr/{account}/repositories/{group}/{id}

Response Code Definition
200 Submitted delete request is submitted
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account or repository not found
409 Conflict repository is not in the available state
500 Internal Server Error a server error occurred

Images

List images in a repository

GET /v1/ecr/{account}/repositories/{group}/{id}/images

Response Code Definition
200 OK return list of images
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account or repository not found
500 Internal Server Error a server error occurred
Example response body
[
    {
        "ArtifactMediaType": "application/vnd.docker.container.image.v1+json",
        "ImageDigest": "sha256:ac81321d3627bcde149b383220b16dabc590f2d247f4c72c64cb14f58e7fb9c2",
        "ImageManifestMediaType": "application/vnd.docker.distribution.manifest.v2+json",
        "ImagePushedAt": "2020-12-14T15:56:11Z",
        "ImageScanFindingsSummary": {
            "FindingSeverityCounts": {},
            "ImageScanCompletedAt": "2020-12-14T16:02:36Z",
            "VulnerabilitySourceUpdatedAt": "2020-11-04T01:21:09Z"
        },
        "ImageScanStatus": {
            "Description": "The scan was completed successfully.",
            "Status": "COMPLETE"
        },
        "ImageSizeInBytes": 16093514,
        "ImageTags": [
            "latest"
        ],
        "RegistryId": "0123456789",
        "RepositoryName": "spindev-00001/myAwesomeRepository"
    }
]

Get details about an image tag

GET /v1/ecr/{account}/repositories/{group}/{id}/images/{tag}

Response Code Definition
200 OK return scanning results
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account or repository not found
500 Internal Server Error a server error occurred
Example response body
{
    "FindingSeverityCounts": {
        "HIGH": 1,
        "INFORMATIONAL": 61,
        "LOW": 17,
        "MEDIUM": 22,
        "UNDEFINED": 5
    },
    "Findings": [
        {
            "Attributes": [
                {
                    "Key": "package_version",
                    "Value": "2.28-10"
                },
                {
                    "Key": "package_name",
                    "Value": "glibc"
                },
                {
                    "Key": "CVSS2_VECTOR",
                    "Value": "AV:N/AC:M/Au:N/C:N/I:N/A:C"
                },
                {
                    "Key": "CVSS2_SCORE",
                    "Value": "7.1"
                }
            ],
            "Description": "The iconv feature in the GNU C Library (aka glibc or libc6) through 2.32, when processing invalid multi-byte input sequences in the EUC-KR encoding, may have a buffer over-read.",
            "Name": "CVE-2019-25013",
            "Severity": "HIGH",
            "Uri": "https://security-tracker.debian.org/tracker/CVE-2019-25013"
        },
        {
            "Attributes": [
                {
                    "Key": "package_version",
                    "Value": "7.64.0-4+deb10u1"
                },
                {
                    "Key": "package_name",
                    "Value": "curl"
                },
                {
                    "Key": "CVSS2_VECTOR",
                    "Value": "AV:N/AC:L/Au:N/C:N/I:P/A:N"
                },
                {
                    "Key": "CVSS2_SCORE",
                    "Value": "5"
                }
            ],
            "Description": "curl 7.41.0 through 7.73.0 is vulnerable to an improper check for certificate revocation due to insufficient verification of the OCSP response.",
            "Name": "CVE-2020-8286",
            "Severity": "MEDIUM",
            "Uri": "https://security-tracker.debian.org/tracker/CVE-2020-8286"
        },
        ...
    ],
    "ImageScanCompletedAt": "2021-03-11T17:27:30Z",
    "VulnerabilitySourceUpdatedAt": "2021-03-11T07:49:36Z"
}

Delete an image tag

This gets the image scanning results for an image tag.

DELETE /v1/ecr/{account}/repositories/{group}/{id}/images/{tag}

Response Code Definition
200 OK successfully deleted tag
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account or repository not found
500 Internal Server Error a server error occurred
Example response body
{
    "Failures": [],
    "ImageIds": [
        {
            "ImageDigest": "sha256:9da375ff906516f880ab34384c938e02619c4d19655f4ceb815f6bd122a06a68",
            "ImageTag": "v1"
        }
    ]
}

Users

Repository users are created in the same account as the repository. An account is "bootstrapped" by the create action if its not already prepared to contain repository users. This bootstrapping creates a shared role and group for admin users. The role grants a user access to a repository based on the tags spinup:org, spinup:spaceid and ResourceName (the repository name). Usernames are a combination of the reponame and the username (reponame-username) to aid in uniqueness. That combination must be unique within the AWS account.

List all users for a repository

GET /v1/ecr/{account}/repositories/{group}/{name}/users

Response Code Definition
200 OK return the list of users
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account not found
500 Internal Server Error a server error occurred
Example list users response
[
    "user1"
]

Create a user

POST /v1/ecr/{account}/repositories/{group}/{name}/users

Response Code Definition
200 OK create a repository
400 Bad Request badly formed request
404 Not Found account not found
500 Internal Server Error a server error occurred
Example create user request body
{
    "username": "user1",
    "tags": [
        {
            "key": "application",
            "value": "myapp"
        }
    ],
    "groups": [
        "SpinupECRAdminGroup"
    ]
}
Example create user response body
{
    "UserName": "user1",
    "AccessKeys": [],
    "Groups": [
        "SpinupECRAdminGroup"
    ],
    "Tags": [
        {
            "Key": "application",
            "Value": "myapp"
        },
        {
            "Key": "ResourceName",
            "Value": "spindev-00001-myAwesomeRepository-user1"
        },
        {
            "Key": "ResourceName",
            "Value": "spindev-00001/myAwesomeRepository"
        },
        {
            "Key": "spinup:org",
            "Value": "spindev"
        },
        {
            "Key": "spinup:spaceid",
            "Value": "spindev-00001"
        }
    ]
}

Get details about a user

GET /v1/ecr/{account}/repositories/{group}/{name}/users/{user}

Response Code Definition
200 OK return details of a user
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account or user not found
500 Internal Server Error a server error occurred
Example show user response
{
    "UserName": "user1",
    "AccessKeys": [],
    "Groups": [
        "SpinupECRAdminGroup"
    ],
    "Tags": [
        {
            "Key": "application",
            "Value": "myapps"
        },
        {
            "Key": "ResourceName",
            "Value": "spindev-00001-myAwesomeRepository-user1"
        },
        {
            "Key": "Name",
            "Value": "spindev-00001/myAwesomeRepository"
        },
        {
            "Key": "spinup:org",
            "Value": "spindev"
        },
        {
            "Key": "spinup:spaceid",
            "Value": "spindev-00001"
        }
    ]
}

Update a user

A user's tags and/or its access key can be updated. The operations are independent, and can occur in the same request, or individually. If the access key is reset, a new access key will be returned with the response.

PUT /v1/ecr/{account}/repositories/{group}/{name}/users/{user}

Response Code Definition
200 OK updated the user
400 Bad Request badly formed request
404 Not Found account not found
500 Internal Server Error a server error occurred
Example update user request body
{
    "resetkey": true,
    "tags": [
        {
            "key": "application",
            "value": "myapp123"
        }
    ],
}
Example update user response
{
    "UserName": "user1",
    "AccessKey": {
        "AccessKeyId": "AAAAABBBBBCCCCCDDDDDEEEEEFFFFF",
        "CreateDate": "2021-02-03T22:37:30Z",
        "SecretAccessKey": "gxyz1234567890abcdefghijklmnop",
        "Status": "Active",
        "UserName": "spincool-00001-testrepo1-user1"
    },
    "DeletedAccessKeys": [
        "QQQQQRRRRRSSSSSTTTTTUUUUVVVV"
    ],
    "Tags": [
        {
            "Key": "application",
            "Value": "myapp123"
        },
        {
            "Key": "ResourceName",
            "Value": "spindev-00001-myAwesomeRepository-user1"
        },
        {
            "Key": "Name",
            "Value": "spindev-00001/myAwesomeRepository"
        },
        {
            "Key": "spinup:org",
            "Value": "spindev"
        },
        {
            "Key": "spinup:spaceid",
            "Value": "spindev-00001"
        }
    ]
}

Delete a user

DELETE /v1/ecr/{account}/repositories/{group}/{name}/users/{user}

Response Code Definition
200 Submitted delete request is submitted
400 Bad Request badly formed request
403 Forbidden bad token or fail to assume role
404 Not Found account or user not found
409 Conflict user is not in the available state
500 Internal Server Error a server error occurred

License

GNU Affero General Public License v3.0 (GNU AGPLv3)
Copyright © 2020 Yale University