Skip to content

Commit

Permalink
Openapi doc (#37)
Browse files Browse the repository at this point in the history
* Added some openapi yml generated by llm

* compose file for bundling up the openapi yaml

* use docker-in-docker and rake task to handle api publish

* Fix bundled yml ownership; link from index info

* Fix missing verbs GET and DELETE, improved descriptions

* make chown dynamic for openapi-bundled; extra doc info

* remove redocly from compose file

* fix lint
  • Loading branch information
suprjinx authored Sep 25, 2024
1 parent 10ecc33 commit aa5f960
Show file tree
Hide file tree
Showing 8 changed files with 763 additions and 2 deletions.
8 changes: 7 additions & 1 deletion .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",

// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
"features": {
"docker-in-docker": {
"version": "latest",
"moby": true,
"dockerDashComposeVersion": "v1"
}
}

// Use 'forwardPorts' to make a list of ports inside the container available locally.
// This can be used to network with other containers or the host.
Expand Down
3 changes: 2 additions & 1 deletion app/views/info/index.json.jbuilder
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
json.app "astral"
json.description "Astral provides a simplified API for PKI."
json.description "Astral provides a simplified API for PKI and secrets"
json.documentation "#{request.scheme}://#{request.host_with_port}/doc"
json.version "0.0.1"
60 changes: 60 additions & 0 deletions doc/openapi/openapi.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
openapi: 3.0.3
info:
title: Astral
description: API documentation for the Astral application
version: 1.0.0
servers:
- url: http://localhost:3000
description: Local development server

paths:
/up:
get:
summary: Health Check
description: Returns 200 if the app boots without exceptions, otherwise 500.
operationId: getHealthCheck
responses:
'200':
description: Application is up
'500':
description: Application failed to boot properly

/:
get:
summary: Info
description: Basic info about the application
operationId: getRoot
responses:
'200':
description: App info retrieved successfully
content:
application/json:
schema:
type: object
properties:
app:
type: string
description: The app name
example: astral
description:
type: string
description: The app description
example: Astral provides a simplified API for PKI and secrets
documentation:
type: string
description: The api docs location
example: http://localhost:3000/doc
version:
type: string
description: The app version
example: "0.0.1"

/certificates:
$ref: './paths/certificates.yml#/postCertificates'

/secrets:
$ref: './paths/secrets.yml#/postSecrets'

/secrets/{path}:
$ref: './paths/secrets.yml#/getDeleteSecrets'

121 changes: 121 additions & 0 deletions doc/openapi/paths/certificates.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
postCertificates:
post:
summary: Create Certificate
description: Issues a new certificate for the provided properties, using the Astral intermediate CA.
operationId: createCertificate
requestBody:
description: Certificate creation data
required: true
content:
application/json:
schema:
type: object
properties:
common_name:
type: string
description: "Common name for the certificate"
example: "example.com"
alt_names:
type: string
description: "Alternative names for the certificate (comma-separated)"
example: "www.example.com,mail.example.com"
exclude_cn_from_sans:
type: boolean
description: "Exclude the common name from the subject alternative names (SAN)"
default: false
format:
type: string
description: "Format of the certificate"
enum: ["pem", "der", "pem_bundle"]
default: "pem"
not_after:
type: string
format: date-time
description: "Expiration date for the certificate"
other_sans:
type: string
description: "Other subject alternative names"
example: "DNS:example.org, DNS:example.net"
private_key_format:
type: string
description: "Format of the private key"
enum: ["pem", "der", "pkcs8"]
default: "pem"
remove_roots_from_chain:
type: boolean
description: "Whether to remove root certificates from the certificate chain"
default: false
ttl:
type: integer
description: "Time to live for the certificate (in seconds)"
example: 86400
uri_sans:
type: string
description: "URI Subject Alternative Names"
example: "http://example.com"
ip_sans:
type: string
description: "IP Subject Alternative Names"
example: "192.168.1.1"
serial_number:
type: integer
description: "Serial number of the certificate"
client_flag:
type: boolean
description: "Indicates if the certificate is for a client"
default: true
code_signing_flag:
type: boolean
description: "Indicates if the certificate is used for code signing"
default: false
email_protection_flag:
type: boolean
description: "Indicates if the certificate provides email protection"
default: false
server_flag:
type: boolean
description: "Indicates if the certificate is for a server"
default: true
responses:
'201':
description: Certificate created successfully
content:
application/json:
schema:
type: object
properties:
ca_chain:
type: array
items:
type: string
description: "Certificate authority chain"
example: ["ca_cert_1", "ca_cert_2"]
certificate:
type: string
description: "Generated certificate"
example: "-----BEGIN CERTIFICATE-----\nMIID...==\n-----END CERTIFICATE-----"
expiration:
type: string
format: date-time
description: "Certificate expiration date"
example: "2024-09-30T00:00:00Z"
issuing_ca:
type: string
description: "Issuing certificate authority"
example: "-----BEGIN CERTIFICATE-----\nMIIC...==\n-----END CERTIFICATE-----"
private_key:
type: string
description: "Private key for the certificate"
example: "-----BEGIN PRIVATE KEY-----\nMIIE...==\n-----END PRIVATE KEY-----"
private_key_type:
type: string
description: "Private key format"
example: "pem"
serial_number:
type: string
description: "Certificate serial number"
example: "1234567890abcdef"
'400':
description: Validation error or bad request
'401':
description: Unauthorized
175 changes: 175 additions & 0 deletions doc/openapi/paths/secrets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
postSecrets:
post:
summary: Create Secret
description: Creates a new secret in the KV store at the provided path.
operationId: createSecret
requestBody:
description: Secret creation data
required: true
content:
application/json:
schema:
type: object
properties:
path:
type: string
description: "Path where the secret is stored"
example: "secret/storage/path"
data:
type: object
description: "The secret data"
example:
key1: "value1"
key2: "value2"
responses:
'201':
description: Secret created successfully
content:
application/json:
schema:
type: object
properties:
request_id:
type: string
description: "Unique ID for the request"
example: "9000000d4-f0000-4c000-000000-800000000f"
lease_id:
type: string
description: "Lease ID"
example: ""
renewable:
type: boolean
description: "Indicates if the secret is renewable"
default: false
lease_duration:
type: integer
description: "Lease duration in seconds"
example: 0
data:
type: object
properties:
created_time:
type: string
format: date-time
description: "The time the secret was created"
example: "2022-02-09T23:41:58.888138788Z"
deletion_time:
type: string
description: "The time the secret was deleted (if applicable)"
example: ""
destroyed:
type: boolean
description: "Indicates if the secret was destroyed"
default: false
version:
type: integer
description: "Version of the secret"
example: 2
wrap_info:
type: object
nullable: true
description: "Wrap information (if applicable)"
warnings:
type: string
nullable: true
description: "Warnings (if any)"
auth:
type: object
nullable: true
description: "Authentication information (if applicable)"
'400':
description: Validation error or bad request
'401':
description: Unauthorized

getDeleteSecrets:
get:
summary: Get Secret
description: Retrieves a secret by its path.
operationId: getSecret
parameters:
- name: path
in: path
required: true
schema:
type: string
description: Path to the secret
responses:
'200':
description: Secret retrieved successfully
content:
application/json:
schema:
type: object
properties:
request_id:
type: string
description: "Unique ID for the request"
example: "9000000d4-f0000-4c000-000000-800000000f"
lease_id:
type: string
description: "Lease ID"
example: ""
renewable:
type: boolean
description: "Indicates if the secret is renewable"
default: false
lease_duration:
type: integer
description: "Lease duration in seconds"
example: 0
data:
type: object
properties:
created_time:
type: string
format: date-time
description: "The time the secret was created"
example: "2022-02-09T23:41:58.888138788Z"
deletion_time:
type: string
description: "The time the secret was deleted (if applicable)"
example: ""
destroyed:
type: boolean
description: "Indicates if the secret was destroyed"
default: false
version:
type: integer
description: "Version of the secret"
example: 2
wrap_info:
type: object
nullable: true
description: "Wrap information (if applicable)"
warnings:
type: string
nullable: true
description: "Warnings (if any)"
auth:
type: object
nullable: true
description: "Authentication information (if applicable)"
'404':
description: Secret not found
'401':
description: Unauthorized

delete:
summary: Delete Secret
description: Deletes a secret by its path.
operationId: deleteSecret
parameters:
- name: path
in: path
required: true
schema:
type: string
description: Path to the secret
responses:
'204':
description: Secret deleted successfully
'404':
description: Secret not found
'401':
description: Unauthorized
Loading

0 comments on commit aa5f960

Please sign in to comment.