From 3566f7ac984ae3758daa9799d1f7a77513d6bae5 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Mon, 27 Apr 2020 21:29:22 +0100 Subject: [PATCH 01/64] updating notes --- tempnotes.md | 11 +++++++++++ todo.md | 25 +++++++++++++++++++------ 2 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 tempnotes.md diff --git a/tempnotes.md b/tempnotes.md new file mode 100644 index 0000000..97b394f --- /dev/null +++ b/tempnotes.md @@ -0,0 +1,11 @@ +# Temp Notes + +## Decoupling + +When creating an ELB instance with `--single` and `--database` the following is created as part of the ELB deployment: + +- security group +- EIP +- RDS database + +Is the security group created without a databse? (probably yes...) diff --git a/todo.md b/todo.md index c547d5c..2df2659 100644 --- a/todo.md +++ b/todo.md @@ -3,20 +3,29 @@ ~~Finish S3 config for env vars~~ ~~Deploy to AWS and ensure vars are working~~ -Use cloudformation to deploy bucket instead of tieing it to the RDS instance. +~~Use cloudformation to deploy bucket instead of tieing it to the RDS instance.~~ Use for bucket options for the template. ~~Strapi documentation - build and host~~ +## RDS Cloudformation + +Use to create an RDS for ELB. + +- RDS cloudformation template +- Use the GUI to go through options and create cloudformation template +- Create an RDS db before deployment + - Configure Strapi to use this RDS db + - VPC + Security Group needs creating in template + +Compare the `--database option` to without and make sure you create everything in the Cloudformation template. + +Look at how to have multiple environments in the same elb app + Deploy strapi as load balanced rather than single instance Deploy strapi with a custom domain with HTTPS as a single instance + load balanced. -RDS cloudformation template - Use the GUI to go through options and create cloudformation template - Create an RDS db before deployment - Configure Strapi to use this RDS db - Combine ELB Documentations (strapi, ELB etc) Use codebuild to update strapi @@ -26,3 +35,7 @@ Use circle CI instead Finish the backgrounds for the demo website Cloudformation template to deploy an S3 bucket + +## Links + +Decouple an exisitng RDS instance from ELB to RDS: From 1338a6677b188e2237aee51c4fea73151401dfdc Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Tue, 28 Apr 2020 20:41:17 +0100 Subject: [PATCH 02/64] adding latest --- .cloudformation/01-stack-storage.yaml | 3 ++ extensions/documentation/public/index.html | 2 +- package-lock.json | 9 +++--- runningnotes.md | 33 ++++++++++++++-------- tempnotes.md | 4 +++ 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/.cloudformation/01-stack-storage.yaml b/.cloudformation/01-stack-storage.yaml index cf861d3..f914d9e 100644 --- a/.cloudformation/01-stack-storage.yaml +++ b/.cloudformation/01-stack-storage.yaml @@ -1,5 +1,8 @@ AWSTemplateFormatVersion: 2010-09-09 Description: S3 bucket for static assets for Strapi deployment. +Parameters: + TestParameter: + Type: String Resources: ELBExampleBucket: Type: "AWS::S3::Bucket" diff --git a/extensions/documentation/public/index.html b/extensions/documentation/public/index.html index 33f96d2..f97b44f 100644 --- a/extensions/documentation/public/index.html +++ b/extensions/documentation/public/index.html @@ -453,7 +453,7 @@ // Build a system const ui = SwaggerUIBundle({ url: "https://petstore.swagger.io/v2/swagger.json", - spec: {"openapi":"3.0.0","info":{"version":"1.0.0","title":"DOCUMENTATION","description":"","termsOfService":"YOUR_TERMS_OF_SERVICE_URL","contact":{"name":"TEAM","email":"contact-email@something.io","url":"mywebsite.io"},"license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0.html"},"x-generation-date":"04/26/2020 5:27:45 PM"},"x-strapi-config":{"path":"/documentation","showGeneratedFiles":true,"generateDefaultResponse":true},"servers":[{"url":"http://localhost:1337","description":"Development server"},{"url":"YOUR_STAGING_SERVER","description":"Staging server"},{"url":"YOUR_PRODUCTION_SERVER","description":"Production server"}],"externalDocs":{"description":"Find out more","url":"https://strapi.io/documentation/3.0.0-beta.x/"},"security":[{"bearerAuth":[]}],"paths":{"/homepage":{"get":{"deprecated":false,"description":"Find all the homepage's records","responses":{"200":{"description":"Retrieve homepage document(s)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Homepage"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Homepage"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]},"put":{"deprecated":false,"description":"Update a single homepage record","responses":{"200":{"description":"Retrieve homepage document(s)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Homepage"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Homepage"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewHomepage"}}}},"parameters":[]},"delete":{"deprecated":false,"description":"Delete a single homepage record","responses":{"200":{"description":"deletes a single homepage based on the ID supplied","content":{"application/json":{"schema":{"type":"integer","format":"int64"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Homepage"],"parameters":[]}},"/tests":{"get":{"deprecated":false,"description":"","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Test"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]},"post":{"deprecated":false,"description":"Create a new record","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Test"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewTest"}}}}}},"/tests/count":{"get":{"deprecated":false,"description":"","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[]}},"/tests/{id}":{"get":{"deprecated":false,"description":"","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Test"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"put":{"deprecated":false,"description":"Update a record","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Test"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewTest"}}}},"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"delete":{"deprecated":false,"description":"Delete a record","responses":{"200":{"description":"deletes a single record based on the ID supplied","content":{"application/json":{"schema":{"type":"integer","format":"int64"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/email/":{"post":{"deprecated":false,"description":"Send an email","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Email - Email"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/upload/":{"post":{"deprecated":false,"description":"Upload a file","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/upload/files/count":{"get":{"deprecated":false,"description":"Retrieve the total number of uploaded files","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[]}},"/upload/files":{"get":{"deprecated":false,"description":"Retrieve all file documents","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[]}},"/upload/files/{id}":{"get":{"deprecated":false,"description":"Retrieve a single file depending on its id","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"delete":{"deprecated":false,"description":"Delete an uploaded file","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/upload/search/{id}":{"get":{"deprecated":false,"description":"Search for an uploaded file","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/users-permissions/init":{"get":{"deprecated":false,"description":"Check if the first admin user has already been registered","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[]}},"/users-permissions/roles/{id}":{"get":{"deprecated":false,"description":"Retrieve a role depending on its id","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/users-permissions/roles":{"get":{"deprecated":false,"description":"Retrieve all role documents","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]},"post":{"deprecated":false,"description":"Create a new role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsRole"}}}}}},"/users-permissions/roles/{role}":{"put":{"deprecated":false,"description":"Update a role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"role","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsRole"}}}}},"delete":{"deprecated":false,"description":"Delete a role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"role","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/users-permissions/search/{id}":{"get":{"deprecated":false,"description":"Search for users","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}},{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]}},"/connect/*":{"get":{"deprecated":false,"description":"Connect a provider","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[]}},"/auth/local":{"post":{"deprecated":false,"description":"Login a user using the identifiers email and password","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/auth/local/register":{"post":{"deprecated":false,"description":"Register a new user with the default role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsUser"}}}}}},"/auth/{provider}/callback":{"get":{"deprecated":false,"description":"Successfull redirection after approving a provider","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"provider","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/auth/forgot-password":{"post":{"deprecated":false,"description":"Send the reset password email link","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/auth/reset-password":{"post":{"deprecated":false,"description":"Change a user's password","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/auth/email-confirmation":{"get":{"deprecated":false,"description":"Validate a user account","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[]}},"/auth/send-email-confirmation":{"post":{"deprecated":false,"description":"Send a confirmation email to user","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/users":{"get":{"deprecated":false,"description":"Retrieve all user documents","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]}},"/users/me":{"get":{"deprecated":false,"description":"Retrieve the logged in user information","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[]}},"/users/{id}":{"get":{"deprecated":false,"description":"Retrieve a single user depending on his id","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"put":{"deprecated":false,"description":"Update an existing user","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsUser"}}}}},"delete":{"deprecated":false,"description":"Delete an existing user","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}}},"components":{"schemas":{"Homepage":{"required":["id"],"properties":{"id":{"type":"string"},"Content":{"type":"string"},"Title":{"type":"string"},"Banner1":{"type":"string"},"Banner2":{"type":"string"},"Image1":{"type":"array","items":{"required":["id","name","hash","mime","size","url","provider"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"alternativeText":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"formats":{"type":"object"},"hash":{"type":"string"},"ext":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"previewUrl":{"type":"string"},"provider":{"type":"string"},"provider_metadata":{"type":"object"},"related":{"type":"string"}}}},"Image2":{"type":"array","items":{"required":["id","name","hash","mime","size","url","provider"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"alternativeText":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"formats":{"type":"object"},"hash":{"type":"string"},"ext":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"previewUrl":{"type":"string"},"provider":{"type":"string"},"provider_metadata":{"type":"object"},"related":{"type":"string"}}}},"Image3":{"type":"array","items":{"required":["id","name","hash","mime","size","url","provider"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"alternativeText":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"formats":{"type":"object"},"hash":{"type":"string"},"ext":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"previewUrl":{"type":"string"},"provider":{"type":"string"},"provider_metadata":{"type":"object"},"related":{"type":"string"}}}}}},"NewHomepage":{"properties":{"Content":{"type":"string"},"Title":{"type":"string"},"Banner1":{"type":"string"},"Banner2":{"type":"string"}}},"Test":{"required":["id"],"properties":{"id":{"type":"string"},"title":{"type":"string"}}},"NewTest":{"properties":{"title":{"type":"string"}}},"UsersPermissionsRole":{"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string","minLength":3},"description":{"type":"string"},"type":{"type":"string"},"permissions":{"type":"array","items":{"required":["id","type","controller","action","enabled"],"properties":{"id":{"type":"string"},"type":{"type":"string"},"controller":{"type":"string"},"action":{"type":"string"},"enabled":{"type":"boolean"},"policy":{"type":"string"},"role":{"type":"string"}}}},"users":{"type":"array","items":{"required":["id","username","email"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"email":{"type":"string"},"provider":{"type":"string"},"password":{"type":"string"},"resetPasswordToken":{"type":"string"},"confirmed":{"type":"boolean"},"blocked":{"type":"boolean"},"role":{"type":"string"}}}}}},"NewUsersPermissionsRole":{"required":["name"],"properties":{"name":{"type":"string","minLength":3},"description":{"type":"string"},"type":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}},"users":{"type":"array","items":{"type":"string"}}}},"UsersPermissionsUser":{"required":["id","username","email"],"properties":{"id":{"type":"string"},"username":{"type":"string","minLength":3},"email":{"type":"string","minLength":6},"provider":{"type":"string"},"confirmed":{"type":"boolean","default":false},"blocked":{"type":"boolean","default":false},"role":{"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}},"users":{"type":"array","items":{"type":"string"}}}}}},"NewUsersPermissionsUser":{"required":["username","email"],"properties":{"username":{"type":"string","minLength":3},"email":{"type":"string","minLength":6},"provider":{"type":"string"},"password":{"type":"string","minLength":6},"resetPasswordToken":{"type":"string"},"confirmed":{"type":"boolean","default":false},"blocked":{"type":"boolean","default":false},"role":{"type":"string"}}},"Error":{"required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"tags":[{"name":"Homepage"},{"name":"Test"},{"name":"Email - Email"},{"name":"Upload - File"},{"name":"UsersPermissions - Role"},{"name":"UsersPermissions - User"}]}, + spec: {"openapi":"3.0.0","info":{"version":"1.0.0","title":"DOCUMENTATION","description":"","termsOfService":"YOUR_TERMS_OF_SERVICE_URL","contact":{"name":"TEAM","email":"contact-email@something.io","url":"mywebsite.io"},"license":{"name":"Apache 2.0","url":"https://www.apache.org/licenses/LICENSE-2.0.html"},"x-generation-date":"04/26/2020 9:40:09 PM"},"x-strapi-config":{"path":"/documentation","showGeneratedFiles":true,"generateDefaultResponse":true},"servers":[{"url":"http://localhost:1337","description":"Development server"},{"url":"YOUR_STAGING_SERVER","description":"Staging server"},{"url":"http://strapi-prod.eu-west-1.elasticbeanstalk.com","description":"Production server"}],"externalDocs":{"description":"Find out more","url":"https://strapi.io/documentation/3.0.0-beta.x/"},"security":[{"bearerAuth":[]}],"paths":{"/about":{"get":{"deprecated":false,"description":"Find all the about's records","responses":{"200":{"description":"Retrieve about document(s)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/About"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["About"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]},"put":{"deprecated":false,"description":"Update a single about record","responses":{"200":{"description":"Retrieve about document(s)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/About"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["About"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewAbout"}}}},"parameters":[]},"delete":{"deprecated":false,"description":"Delete a single about record","responses":{"200":{"description":"deletes a single about based on the ID supplied","content":{"application/json":{"schema":{"type":"integer","format":"int64"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["About"],"parameters":[]}},"/homepage":{"get":{"deprecated":false,"description":"Find all the homepage's records","responses":{"200":{"description":"Retrieve homepage document(s)","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Homepage"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Homepage"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]},"put":{"deprecated":false,"description":"Update a single homepage record","responses":{"200":{"description":"Retrieve homepage document(s)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Homepage"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Homepage"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewHomepage"}}}},"parameters":[]},"delete":{"deprecated":false,"description":"Delete a single homepage record","responses":{"200":{"description":"deletes a single homepage based on the ID supplied","content":{"application/json":{"schema":{"type":"integer","format":"int64"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Homepage"],"parameters":[]}},"/tests":{"get":{"deprecated":false,"description":"","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Test"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]},"post":{"deprecated":false,"description":"Create a new record","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Test"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewTest"}}}}}},"/tests/count":{"get":{"deprecated":false,"description":"","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"count":{"type":"integer"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[]}},"/tests/{id}":{"get":{"deprecated":false,"description":"","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Test"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"put":{"deprecated":false,"description":"Update a record","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Test"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewTest"}}}},"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"delete":{"deprecated":false,"description":"Delete a record","responses":{"200":{"description":"deletes a single record based on the ID supplied","content":{"application/json":{"schema":{"type":"integer","format":"int64"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Test"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/email/":{"post":{"deprecated":false,"description":"Send an email","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Email - Email"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/upload/":{"post":{"deprecated":false,"description":"Upload a file","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/upload/files/count":{"get":{"deprecated":false,"description":"Retrieve the total number of uploaded files","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[]}},"/upload/files":{"get":{"deprecated":false,"description":"Retrieve all file documents","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[]}},"/upload/files/{id}":{"get":{"deprecated":false,"description":"Retrieve a single file depending on its id","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"delete":{"deprecated":false,"description":"Delete an uploaded file","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/upload/search/{id}":{"get":{"deprecated":false,"description":"Search for an uploaded file","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["Upload - File"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/users-permissions/init":{"get":{"deprecated":false,"description":"Check if the first admin user has already been registered","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[]}},"/users-permissions/roles/{id}":{"get":{"deprecated":false,"description":"Retrieve a role depending on its id","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/users-permissions/roles":{"get":{"deprecated":false,"description":"Retrieve all role documents","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]},"post":{"deprecated":false,"description":"Create a new role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsRole"}}}}}},"/users-permissions/roles/{role}":{"put":{"deprecated":false,"description":"Update a role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsRole"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"role","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsRole"}}}}},"delete":{"deprecated":false,"description":"Delete a role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - Role"],"parameters":[{"name":"role","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/users-permissions/search/{id}":{"get":{"deprecated":false,"description":"Search for users","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}},{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]}},"/connect/*":{"get":{"deprecated":false,"description":"Connect a provider","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[]}},"/auth/local":{"post":{"deprecated":false,"description":"Login a user using the identifiers email and password","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/auth/local/register":{"post":{"deprecated":false,"description":"Register a new user with the default role","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsUser"}}}}}},"/auth/{provider}/callback":{"get":{"deprecated":false,"description":"Successfull redirection after approving a provider","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"provider","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}},"/auth/forgot-password":{"post":{"deprecated":false,"description":"Send the reset password email link","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/auth/reset-password":{"post":{"deprecated":false,"description":"Change a user's password","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/auth/email-confirmation":{"get":{"deprecated":false,"description":"Validate a user account","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[]}},"/auth/send-email-confirmation":{"post":{"deprecated":false,"description":"Send a confirmation email to user","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}}}},"/users":{"get":{"deprecated":false,"description":"Retrieve all user documents","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"_limit","in":"query","required":false,"description":"Maximum number of results possible","schema":{"type":"integer"},"deprecated":false},{"name":"_sort","in":"query","required":false,"description":"Sort according to a specific field.","schema":{"type":"string"},"deprecated":false},{"name":"_start","in":"query","required":false,"description":"Skip a specific number of entries (especially useful for pagination)","schema":{"type":"integer"},"deprecated":false},{"name":"=","in":"query","required":false,"description":"Get entries that matches exactly your input","schema":{"type":"string"},"deprecated":false},{"name":"_ne","in":"query","required":false,"description":"Get records that are not equals to something","schema":{"type":"string"},"deprecated":false},{"name":"_lt","in":"query","required":false,"description":"Get record that are lower than a value","schema":{"type":"string"},"deprecated":false},{"name":"_lte","in":"query","required":false,"description":"Get records that are lower than or equal to a value","schema":{"type":"string"},"deprecated":false},{"name":"_gt","in":"query","required":false,"description":"Get records that are greater than a value","schema":{"type":"string"},"deprecated":false},{"name":"_gte","in":"query","required":false,"description":"Get records that are greater than or equal a value","schema":{"type":"string"},"deprecated":false},{"name":"_contains","in":"query","required":false,"description":"Get records that contains a value","schema":{"type":"string"},"deprecated":false},{"name":"_containss","in":"query","required":false,"description":"Get records that contains (case sensitive) a value","schema":{"type":"string"},"deprecated":false},{"name":"_in","in":"query","required":false,"description":"Get records that matches any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false},{"name":"_nin","in":"query","required":false,"description":"Get records that doesn't match any value in the array of values","schema":{"type":"array","items":{"type":"string"}},"deprecated":false}]}},"/users/me":{"get":{"deprecated":false,"description":"Retrieve the logged in user information","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[]}},"/users/{id}":{"get":{"deprecated":false,"description":"Retrieve a single user depending on his id","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]},"put":{"deprecated":false,"description":"Update an existing user","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsersPermissionsUser"}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}],"requestBody":{"description":"","required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NewUsersPermissionsUser"}}}}},"delete":{"deprecated":false,"description":"Delete an existing user","responses":{"200":{"description":"response","content":{"application/json":{"schema":{"properties":{"foo":{"type":"string"}}}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"default":{"description":"unexpected error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"summary":"","tags":["UsersPermissions - User"],"parameters":[{"name":"id","in":"path","description":"","deprecated":false,"required":true,"schema":{"type":"string"}}]}}},"components":{"schemas":{"About":{"required":["id"],"properties":{"id":{"type":"string"},"Content":{"type":"string"},"Title":{"type":"string"},"Video":{"type":"array","items":{"required":["id","name","hash","mime","size","url","provider"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"alternativeText":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"formats":{"type":"object"},"hash":{"type":"string"},"ext":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"previewUrl":{"type":"string"},"provider":{"type":"string"},"provider_metadata":{"type":"object"},"related":{"type":"string"}}}},"Optionextra":{"type":"string"}}},"NewAbout":{"properties":{"Content":{"type":"string"},"Title":{"type":"string"},"Optionextra":{"type":"string"}}},"Homepage":{"required":["id"],"properties":{"id":{"type":"string"},"Content":{"type":"string"},"Title":{"type":"string"},"Banner1":{"type":"string"},"Banner2":{"type":"string"},"Image1":{"type":"array","items":{"required":["id","name","hash","mime","size","url","provider"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"alternativeText":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"formats":{"type":"object"},"hash":{"type":"string"},"ext":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"previewUrl":{"type":"string"},"provider":{"type":"string"},"provider_metadata":{"type":"object"},"related":{"type":"string"}}}},"Image2":{"type":"array","items":{"required":["id","name","hash","mime","size","url","provider"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"alternativeText":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"formats":{"type":"object"},"hash":{"type":"string"},"ext":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"previewUrl":{"type":"string"},"provider":{"type":"string"},"provider_metadata":{"type":"object"},"related":{"type":"string"}}}},"Image3":{"type":"array","items":{"required":["id","name","hash","mime","size","url","provider"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"alternativeText":{"type":"string"},"caption":{"type":"string"},"width":{"type":"integer"},"height":{"type":"integer"},"formats":{"type":"object"},"hash":{"type":"string"},"ext":{"type":"string"},"mime":{"type":"string"},"size":{"type":"number"},"url":{"type":"string"},"previewUrl":{"type":"string"},"provider":{"type":"string"},"provider_metadata":{"type":"object"},"related":{"type":"string"}}}}}},"NewHomepage":{"properties":{"Content":{"type":"string"},"Title":{"type":"string"},"Banner1":{"type":"string"},"Banner2":{"type":"string"}}},"Test":{"required":["id"],"properties":{"id":{"type":"string"},"title":{"type":"string"}}},"NewTest":{"properties":{"title":{"type":"string"}}},"UsersPermissionsRole":{"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string","minLength":3},"description":{"type":"string"},"type":{"type":"string"},"permissions":{"type":"array","items":{"required":["id","type","controller","action","enabled"],"properties":{"id":{"type":"string"},"type":{"type":"string"},"controller":{"type":"string"},"action":{"type":"string"},"enabled":{"type":"boolean"},"policy":{"type":"string"},"role":{"type":"string"}}}},"users":{"type":"array","items":{"required":["id","username","email"],"properties":{"id":{"type":"string"},"username":{"type":"string"},"email":{"type":"string"},"provider":{"type":"string"},"password":{"type":"string"},"resetPasswordToken":{"type":"string"},"confirmed":{"type":"boolean"},"blocked":{"type":"boolean"},"role":{"type":"string"}}}}}},"NewUsersPermissionsRole":{"required":["name"],"properties":{"name":{"type":"string","minLength":3},"description":{"type":"string"},"type":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}},"users":{"type":"array","items":{"type":"string"}}}},"UsersPermissionsUser":{"required":["id","username","email"],"properties":{"id":{"type":"string"},"username":{"type":"string","minLength":3},"email":{"type":"string","minLength":6},"provider":{"type":"string"},"confirmed":{"type":"boolean","default":false},"blocked":{"type":"boolean","default":false},"role":{"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string"},"permissions":{"type":"array","items":{"type":"string"}},"users":{"type":"array","items":{"type":"string"}}}}}},"NewUsersPermissionsUser":{"required":["username","email"],"properties":{"username":{"type":"string","minLength":3},"email":{"type":"string","minLength":6},"provider":{"type":"string"},"password":{"type":"string","minLength":6},"resetPasswordToken":{"type":"string"},"confirmed":{"type":"boolean","default":false},"blocked":{"type":"boolean","default":false},"role":{"type":"string"}}},"Error":{"required":["code","message"],"properties":{"code":{"type":"integer","format":"int32"},"message":{"type":"string"}}}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"}}},"tags":[{"name":"About"},{"name":"Homepage"},{"name":"Test"},{"name":"Email - Email"},{"name":"Upload - File"},{"name":"UsersPermissions - Role"},{"name":"UsersPermissions - User"}]}, dom_id: '#swagger-ui', docExpansion: "none", deepLinking: true, diff --git a/package-lock.json b/package-lock.json index 0140afa..449d2ee 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9882,13 +9882,12 @@ "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" }, "sqlite3": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.1.1.tgz", - "integrity": "sha512-CvT5XY+MWnn0HkbwVKJAyWEMfzpAPwnTiB3TobA5Mri44SrTovmmh499NPQP+gatkeOipqPlBLel7rn4E/PCQg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.2.0.tgz", + "integrity": "sha512-roEOz41hxui2Q7uYnWsjMOTry6TcNUNmp8audCx18gF10P2NknwdpF+E+HKvz/F2NvPKGGBF4NGc+ZPQ+AABwg==", "requires": { "nan": "^2.12.1", - "node-pre-gyp": "^0.11.0", - "request": "^2.87.0" + "node-pre-gyp": "^0.11.0" } }, "sshpk": { diff --git a/runningnotes.md b/runningnotes.md index 9ce51f5..997984a 100644 --- a/runningnotes.md +++ b/runningnotes.md @@ -1,20 +1,9 @@ # Running notes -create an elb with --single and --database - -redeploy with username option set, does it change? - -Does strapi work with a databse set in production mode? - -SSH into EC2 - check if its using sqlite - deocument that the db has to be done from cli arg, but the configs can be done via files. SSL? https://levelup.gitconnected.com/beginners-guide-to-aws-beanstalk-using-node-js-d061bb4b8755 -Add postgres to strapi -Add the S3 bucket to strapi - If doesnt work, try installing yarn in the ELB instance Create seperate sql database + VPC rules: @@ -174,6 +163,22 @@ An example is: } ``` +## Strapi in git + +To have a strapi project in github you should remove the: + +- `./build` +- `./node_modules` + +folders. + +When cloning from the repo you should then do a: + +- `NODE_ENV=development npm install` +- `NODE_ENV=development npm run build` + +You can then run Strapi with `npm run develop` or `NODE_ENV=production npm run start`. + ## Cloudformation (example of deploying an S3 bucket with static site `index.html`.) @@ -219,6 +224,10 @@ Using stacks means AWS will treat all resources as a single unit. They must all `aws --profile admin cloudformation deploy --template-file ./01-stack-storage.yaml --stack-name strapi-s3` +You can pass paramter values in with `--paramter-overrides KEY=VALUE`: + +`--parameter-overrides TestParameter="some test string"` + #### Destroy a stack `aws --profile admin cloudformation delete-stack --stack-name strapi-s3` @@ -236,7 +245,7 @@ Suggested tags for all AWS resources are: | environment | environment resource belongs to | `dev`, `prod` | | deployment | AWS tool used for deployment | `cloudformation`, `elb` | -### Cloudformation +### Cloudformation default tags For Cloudformation resources the following tags get applied automatically: diff --git a/tempnotes.md b/tempnotes.md index 97b394f..013d89e 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -9,3 +9,7 @@ When creating an ELB instance with `--single` and `--database` the following is - RDS database Is the security group created without a databse? (probably yes...) + +## Creating Database + VPC + Subnets in Cloudformation + +Template from AWS showing cross-stack referencing and creating and referencing a VPC: . From 08708011b8b534668fbb3a9e6fc4492b57550a52 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 02:25:57 +0100 Subject: [PATCH 03/64] adding cloudformation templates --- .cloudformation/02-stack-vpc.yaml | 93 +++++++++++++++++++++++ .cloudformation/03-stack-rdsinstance.yaml | 13 ++++ 2 files changed, 106 insertions(+) create mode 100644 .cloudformation/02-stack-vpc.yaml create mode 100644 .cloudformation/03-stack-rdsinstance.yaml diff --git a/.cloudformation/02-stack-vpc.yaml b/.cloudformation/02-stack-vpc.yaml new file mode 100644 index 0000000..53a46a6 --- /dev/null +++ b/.cloudformation/02-stack-vpc.yaml @@ -0,0 +1,93 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: VPC and Subnet definitions for Strapi + ELB project. +Resources: + PublicVPC: + Type: AWS::EC2::VPC + Properties: + CidrBlock: "172.31.0.0/16" + EnableDnsHostnames: true + EnableDnsSupport: true + PublicSubnet0: + Type: AWS::EC2::Subnet + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: !Ref "AWS::Region" + VpcId: !Ref PublicVPC + CidrBlock: 172.31.0.0/20 + MapPublicIpOnLaunch: true + PublicSubnet1: + Type: AWS::EC2::Subnet + Properties: + AvailabilityZone: + Fn::Select: + - 1 + - Fn::GetAZs: !Ref "AWS::Region" + VpcId: !Ref PublicVPC + CidrBlock: 172.31.16.0/20 + MapPublicIpOnLaunch: true + PublicSubnet2: + Type: AWS::EC2::Subnet + Properties: + AvailabilityZone: + Fn::Select: + - 2 + - Fn::GetAZs: !Ref "AWS::Region" + VpcId: !Ref PublicVPC + CidrBlock: 172.31.32.0/20 + MapPublicIpOnLaunch: true + InternetGateway: + Type: AWS::EC2::InternetGateway + InternetGatewayAttachment: + Type: AWS::EC2::VPCGatewayAttachment + Properties: + VpcId: !Ref PublicVPC + InternetGatewayId: !Ref InternetGateway + PublicRouteTable: + Type: AWS::EC2::RouteTable + Properties: + VpcId: !Ref PublicVPC + PublicRoute: + Type: AWS::EC2::Route + DependsOn: InternetGatewayAttachment + Properties: + RouteTableId: !Ref PublicRouteTable + DestinationCidrBlock: 0.0.0.0/0 + GatewayId: !Ref InternetGateway + PublicSubnet0RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref PublicSubnet0 + RouteTableId: !Ref PublicRouteTable + PublicSubnet1RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref PublicSubnet1 + RouteTableId: !Ref PublicRouteTable + PublicSubnet2RouteTableAssociation: + Type: AWS::EC2::SubnetRouteTableAssociation + Properties: + SubnetId: !Ref PublicSubnet2 + RouteTableId: !Ref PublicRouteTable +Outputs: + PublicVPCID: + Description: The VPC ID. + Value: !Ref PublicVPC + Export: + Name: ELBStrapiPublicVPC + PublicSubnet0ID: + Description: The ID of the subnet. + Value: !Ref PublicSubnet0 + Export: + Name: ELBStrapiSubnet0 + PublicSubnet1ID: + Description: The ID of the subnet. + Value: !Ref PublicSubnet1 + Export: + Name: ELBStrapiSubnet1 + PublicSubnet2ID: + Description: The ID of the subnet. + Value: !Ref PublicSubnet2 + Export: + Name: ELBStrapiSubnet2 diff --git a/.cloudformation/03-stack-rdsinstance.yaml b/.cloudformation/03-stack-rdsinstance.yaml new file mode 100644 index 0000000..4826da5 --- /dev/null +++ b/.cloudformation/03-stack-rdsinstance.yaml @@ -0,0 +1,13 @@ +AWSTemplateFormatVersion: 2010-09-09 +Description: RDS and settings for ELB strapi deployment. +Metadata: + +Parameters: + +Mappings: + +Conditions: + +Resources: + +Outputs: From 7daf5069ef5d5b648a39d19a658e9f85f1879a4b Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 02:26:07 +0100 Subject: [PATCH 04/64] updating notes --- runningnotes.md | 113 +++++++++++++++++++++++++++++++++++++++++++++++- tempnotes.md | 88 +++++++++++++++++++++++++++++++++++++ todo.md | 6 +++ 3 files changed, 206 insertions(+), 1 deletion(-) diff --git a/runningnotes.md b/runningnotes.md index 997984a..15d3906 100644 --- a/runningnotes.md +++ b/runningnotes.md @@ -183,6 +183,8 @@ You can then run Strapi with `npm run develop` or `NODE_ENV=production npm run s (example of deploying an S3 bucket with static site `index.html`.) +### Creating templates + To create a cloudformation template you should create a `template.yaml`. This yaml file should have at the top: ```yaml @@ -192,16 +194,125 @@ Description: A simple CloudFormation template Then you should add a `Resources` key and populate this with all the infrastructure you need to provision. -### Creating templates +### Adding resources Documentation for all AWS resources is: . A good approach is to use the GUI to create an object, and then lookup the cloudformation template as you go along. +### Using parameters + + + +You can use parameters in your templates. This allows you to use names/resources from other templates, or specify them at creation on the CLI. + +To use a parameter you should create a `Parameters` section in the yaml on the same level as a `Resources`. + +```yaml +Parameters: + InstanceTypeParameter: + Type: String + Default: t2.micro + AllowedValues: + - t2.micro + - m1.small + - m1.large + Description: Enter t2.micro, m1.small, or m1.large. Default is t2.micro. +``` + +### Using outputs + + + +### Using functions + +A list of all Cloudformation functions is: . + +`Fn::Select` will select a single object from a list of objects by index. + +`Fn::GetAZs` returns an array that lists all availability zones for a specified region. + +`!Ref` returns the value of the specified parameter or resource. + +Example of these: + +```yaml +PublicSubnet1: + Type: AWS::EC2::Subnet + Properties: + AvailabilityZone: + Fn::Select: + - 0 + - Fn::GetAZs: !Ref "AWS::Region" +``` + +### Outputs + +You can use the `Outputs:` header in your Cloudformation templates to specify outputs to be used in other Cloudformation templates. + + + +```yaml +Outputs: + PublicVPCID: + Description: The VPC ID. + Value: !Ref PublicVPC + Export: + Name: ELBStrapiPublicVPC +``` + +`Value` returns the value of the property by an `aws cloudformation describe-stacks` command. The value can contain literals, parameter references, pseudo-parameters, mapping values or functions. + +`Name` goes under `Export:` and is used for cross-stack reference. This name should be unique within a region. You can use this name in other Cloudformation templates to reference the `Value` you have specified above. You can set content in other cloudformation templates this way. + +You can refer to these in ELB `./config` files for example - allowing you to dynamically link to other AWS resources in your ELB environment. + +### Referencing other resources + +You can reference other resources in the template. This is useful say if you want to define a VPC and a subnet and reference the VPC from the subnet. + +To do this you should use the `!Ref` function: + +```yaml +VpcId: !Ref PublicVPC +``` + +#### Pesudeo references + +You can also reference certain AWS references: . + +Examples include `AWS::AccountId` and `AWS::StackName` among others. + ### Deploy a stack/template To deploy, you should run the command: `aws cloudformation deploy --template-file template.yaml --stack-name static-website` +### Tags + +When setting tags you can set them on individual resources in the Cloudformation template: + +```yaml +Tags: + - Key: git + Value: web-dev + - Key: owner + Value: home + - Key: project + Value: strapi-elb + - Key: test + Value: true + - Key: deployment + Value: cloudformation +``` + +Alternatively if you have many tags to be shared across all resources you can set them when you use the CLI to deploy: `--tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` + +### Updating stack + +To update a stack you can use `deploy`. Note that the default behaviour is to create the new resources side by side, then once successful remove the old ones. You may run into errors when updating certain resources (updating a VPC subnet will fail as it has to create the new subnet alongside the existing one). You should remove the old stack by doing `delete-stack` first. + +`aws cloudformation delete-stack --stack-name temp-vpc --profile admin` + ### Failure If something goes wrong, you can use `describe-stack-events` and pass the `stack-name` to find the events leading up to the failure: `aws cloudformation describe-stack-events --stack-name strapi-s3`. diff --git a/tempnotes.md b/tempnotes.md index 013d89e..31714ed 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -13,3 +13,91 @@ Is the security group created without a databse? (probably yes...) ## Creating Database + VPC + Subnets in Cloudformation Template from AWS showing cross-stack referencing and creating and referencing a VPC: . + +Export these in the CF template with stackname () + +A security group is a resource that defines what IPs/Ports are allowed on inbound/outbound for an AWS resource. You can have one for EC2 instance, or RDS among others. + +ELB will create a VPC for your EC2 instances. + +You should use this VPC for you RDS instance. + +Creating a VPC for ELB (with RDS) + +## Single instance (no load balancer) + +Example cloudformation template that ELB uses: . + +Create a VPC - this is an object that spans all availability zones in a region. You assign a VPC a CIDR block. This is a set of IP addresses that this VPC has access to. + +You should create public subnets inside this VPC - these subnets should cover all availablility zones in your region. The CIDR block you specified in the VPC defines all the ips, you should create N subnets that equally contain these IP addresses for your region. + +For example a VPC in `eu-west-1` has a CIDR block of `172.31.0.0/16`. + +There are 3 availablity zones in `eu-west-1`: `eu-west-1a`, `eu-west-1b` and `eu-west-1c`. + +To find other availablity zones you should go to the EC2 Dashboard for the region you want to work in, and scroll down to the Service health header. Here, a list of all availability zones will be shown. + +You should create subnets with the following: + +| Availability Zone | Subnet CIDR | Real IP Range | +| ----------------- | -------------- | --------------------------- | +| `eu-west-1a` | 172.31.0.0/20 | 172.31.0.0 - 172.31.15.255 | +| `eu-west-1b` | 172.31.16.0/20 | 172.31.16.0 - 172.31.31.255 | +| `eu-west-1c` | 172.31.32.0/20 | 172.31.32.0 - 172.31.47.255 | + +This covers all IP addresses across all availability zones in the VPC. + +To make these subnets actually public, you should associate them with an internet gateway. + +An internet gateway is an object that allows communication to the internet. In Cloudformation you should create an internet gateway and a VPC Gateway attachment. This attachment should reference the VPC you have created and reference the internet gateway object you create as well. Then, in your subnets (which are public) you can use `MapPublicIpOnLaunch: true` in the `Properties` block for each subnet. + +You should then create a public route table and associate it with the VPC you have created. + +You should then create a public route. You can then attach the internet gateway attachment to this route and specify a list of IPs that will go out to the internet. To allow all trafic to the internet set a `DestinationCidrBlock` of `0.0.0.0/0`. + +### EC2::VPC + +#### Enable DNS + +Enable `EnableDnsHostnames` + `EnableDnsSupport` - this allows resources in the VPC to use DNS in AWS. + +### EC2::Subnet + +Go to the EC2 dashboard to find all availability zones. Create a subnet for each zone. + +- `AvailabilityZone` +- `VpcId` +- `CidrBlock` +- `MapPublicIpOnLaunch` + +### EC2::InternetGateway + +### EC2::VPCGatewayAttachment + +- `VpcId` +- `InternetGatewayId` + +### AWS::EC2::RouteTable + +- `VpcId` + +### AWS::EC2::Route + +- `RouteTableId` +- `DestinationCidrBlock` +- `GatewayId` + +### AWS::EC2::SubnetRouteTableAssociation + +- `SubnetId` +- `RouteTableId` + +## Running notes + +If we specify the VPC + Subnets from Cloudformation in a config file, will it create the security groups automatically for the EC2 instances? + +Database can use existing subnets. +Database needs a security group creating +EC2 security groups automatically created and associated with the VPC. +Use aws:ec2:vpc (https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc) diff --git a/todo.md b/todo.md index 2df2659..5e3733a 100644 --- a/todo.md +++ b/todo.md @@ -39,3 +39,9 @@ Cloudformation template to deploy an S3 bucket ## Links Decouple an exisitng RDS instance from ELB to RDS: + +Deploy the ELB environment referencing the VPC + Subnets created with Cloudformation. Use https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/vpc-rds.html as a reference. + +Check the security group defined in 06 is created successfully. + +Recreate env with database, check the DB subnets - are they the same as the EC2 subnets? If so we can reference them in https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc with ELBSubnets From b11bf3337f3ca3b3ad91785e0d4fcebf33208190 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 02:27:22 +0100 Subject: [PATCH 05/64] temporarily updating security group --- .ebextensions/06-https-instance-securitygroup.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ebextensions/06-https-instance-securitygroup.config b/.ebextensions/06-https-instance-securitygroup.config index e32bd94..4005ba8 100644 --- a/.ebextensions/06-https-instance-securitygroup.config +++ b/.ebextensions/06-https-instance-securitygroup.config @@ -4,6 +4,6 @@ Resources: Properties: GroupId: { "Fn::GetAtt": ["AWSEBSecurityGroup", "GroupId"] } IpProtocol: tcp - ToPort: 443 - FromPort: 443 + ToPort: 444 + FromPort: 444 CidrIp: 0.0.0.0/0 From dd90c2dcc45f773802a978290e0c9854ea2afca8 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 02:49:37 +0100 Subject: [PATCH 06/64] reverting security group ssl port change --- .ebextensions/06-https-instance-securitygroup.config | 4 ++-- todo.md | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.ebextensions/06-https-instance-securitygroup.config b/.ebextensions/06-https-instance-securitygroup.config index 4005ba8..e32bd94 100644 --- a/.ebextensions/06-https-instance-securitygroup.config +++ b/.ebextensions/06-https-instance-securitygroup.config @@ -4,6 +4,6 @@ Resources: Properties: GroupId: { "Fn::GetAtt": ["AWSEBSecurityGroup", "GroupId"] } IpProtocol: tcp - ToPort: 444 - FromPort: 444 + ToPort: 443 + FromPort: 443 CidrIp: 0.0.0.0/0 diff --git a/todo.md b/todo.md index 5e3733a..523a5cd 100644 --- a/todo.md +++ b/todo.md @@ -44,4 +44,8 @@ Deploy the ELB environment referencing the VPC + Subnets created with Cloudforma Check the security group defined in 06 is created successfully. +When you reference a resource in a config file with resources, if it exists in ELB it will apply that to the existing ELB resource. You can overwrite/append values this way. + +For example setting `sslSecurityGroupIngress:` in a config resources will edit the security group for ssl ingress for your ec2. + Recreate env with database, check the DB subnets - are they the same as the EC2 subnets? If so we can reference them in https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc with ELBSubnets From 01cfc11c4a928962d30acefe86394d12282d7bbe Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 02:57:39 +0100 Subject: [PATCH 07/64] adding custom VPC --- .ebextensions/07-custom-vpc.config | 5 +++++ todo.md | 8 ++------ 2 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 .ebextensions/07-custom-vpc.config diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config new file mode 100644 index 0000000..da36a2a --- /dev/null +++ b/.ebextensions/07-custom-vpc.config @@ -0,0 +1,5 @@ +option_settings: + aws:ec2:vpc: + VPCId: "vpc-003597eb63a0a3efe" + Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" + diff --git a/todo.md b/todo.md index 523a5cd..48cd161 100644 --- a/todo.md +++ b/todo.md @@ -42,10 +42,6 @@ Decouple an exisitng RDS instance from ELB to RDS: Date: Wed, 29 Apr 2020 16:37:00 +0100 Subject: [PATCH 08/64] adding dbsubnets --- .ebextensions/07-custom-vpc.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index da36a2a..7381478 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -2,4 +2,4 @@ option_settings: aws:ec2:vpc: VPCId: "vpc-003597eb63a0a3efe" Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" - + DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" From 92c33e519e54efa6fc19d0072c617011e86bcbef Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 17:16:45 +0100 Subject: [PATCH 09/64] changing VPC to use outputs --- .cloudformation/02-stack-vpc.yaml | 8 ++++---- .ebextensions/07-custom-vpc.config | 2 +- todo.md | 15 ++++++++++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/.cloudformation/02-stack-vpc.yaml b/.cloudformation/02-stack-vpc.yaml index 53a46a6..ef71fb2 100644 --- a/.cloudformation/02-stack-vpc.yaml +++ b/.cloudformation/02-stack-vpc.yaml @@ -75,19 +75,19 @@ Outputs: Description: The VPC ID. Value: !Ref PublicVPC Export: - Name: ELBStrapiPublicVPC + Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC" PublicSubnet0ID: Description: The ID of the subnet. Value: !Ref PublicSubnet0 Export: - Name: ELBStrapiSubnet0 + Name: !Sub "${AWS::StackName}-ELBStrapiSubnet0" PublicSubnet1ID: Description: The ID of the subnet. Value: !Ref PublicSubnet1 Export: - Name: ELBStrapiSubnet1 + Name: !Sub "${AWS::StackName}-ELBStrapiSubnet1" PublicSubnet2ID: Description: The ID of the subnet. Value: !Ref PublicSubnet2 Export: - Name: ELBStrapiSubnet2 + Name: !Sub "${AWS::StackName}-ELBStrapiSubnet2" diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 7381478..9134e2e 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: "vpc-003597eb63a0a3efe" + VPCId: !FN::ImportValue" "temp-vpc-ELBStrapiPublicVPC" Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" diff --git a/todo.md b/todo.md index 48cd161..725527a 100644 --- a/todo.md +++ b/todo.md @@ -42,6 +42,19 @@ Decouple an exisitng RDS instance from ELB to RDS: Date: Wed, 29 Apr 2020 17:18:11 +0100 Subject: [PATCH 10/64] updating FN --- .ebextensions/07-custom-vpc.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 9134e2e..5fc71a1 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: !FN::ImportValue" "temp-vpc-ELBStrapiPublicVPC" + VPCId: !FN::ImportValue "temp-vpc-ELBStrapiPublicVPC" Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" From 35f0468debd59c6ccc7c1089c7f9dc07e3568a8e Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 17:20:47 +0100 Subject: [PATCH 11/64] updating FN --- .ebextensions/07-custom-vpc.config | 2 +- todo.md | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 5fc71a1..c6e6331 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: !FN::ImportValue "temp-vpc-ELBStrapiPublicVPC" + VPCId: FN::ImportValue: "temp-vpc-ELBStrapiPublicVPC" Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" diff --git a/todo.md b/todo.md index 725527a..19a73f8 100644 --- a/todo.md +++ b/todo.md @@ -58,3 +58,21 @@ Can we use cloudformation functions (imports) in .config files under option_sett Append the stackname to the outputs for the VPC and Subnets + +!Sub "${AWS::StackName}-VPCID" + +Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC" +Name: !Sub "${AWS::StackName}-ELBStrapiSubnet0" +Name: !Sub "${AWS::StackName}-ELBStrapiSubnet1" +Name: !Sub "${AWS::StackName}-ELBStrapiSubnet2" + +temp-vpc-ELBStrapiPublicVPC +temp-vpc-ELBStrapiSubnet0 +temp-vpc-ELBStrapiSubnet1 +temp-vpc-ELBStrapiSubnet2 + +{ "Fn::ImportValue": "awseb-e-abcdefghijklmno-AutoScalingGroup" } + +Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ] + +Updating 07 config to accept a parameter From 7092cb003f1f526dfe497e0d8b4524c356fda239 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 17:24:08 +0100 Subject: [PATCH 12/64] updating FN --- .ebextensions/07-custom-vpc.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index c6e6331..d61980a 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: FN::ImportValue: "temp-vpc-ELBStrapiPublicVPC" + VPCId: { "FN::ImportValue": "temp-vpc-ELBStrapiPublicVPC" } Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" From 6b4068f6f81007b2f2e918f7fbf45422f07b799b Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 17:54:07 +0100 Subject: [PATCH 13/64] reverting VPC --- .ebextensions/07-custom-vpc.config | 2 +- todo.md | 21 +-------------------- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index d61980a..7381478 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: { "FN::ImportValue": "temp-vpc-ELBStrapiPublicVPC" } + VPCId: "vpc-003597eb63a0a3efe" Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" diff --git a/todo.md b/todo.md index 19a73f8..8b57e19 100644 --- a/todo.md +++ b/todo.md @@ -55,24 +55,5 @@ option_settings: Recreate env with database, check the DB subnets - are they the same as the EC2 subnets? If so we can reference them in https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc with ELBSubnets Can we use cloudformation functions (imports) in .config files under option_settings? (reference a VPC that already exists?) (https://www.reddit.com/r/aws/comments/a2uoae/is_there_a_way_to_reference_an_elastic_beanstalk/) Yes? +Yes but only certain functions: . You cannot use FN::ImportValue to reference a resource in another Cloudformation stack. - -Append the stackname to the outputs for the VPC and Subnets - -!Sub "${AWS::StackName}-VPCID" - -Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC" -Name: !Sub "${AWS::StackName}-ELBStrapiSubnet0" -Name: !Sub "${AWS::StackName}-ELBStrapiSubnet1" -Name: !Sub "${AWS::StackName}-ELBStrapiSubnet2" - -temp-vpc-ELBStrapiPublicVPC -temp-vpc-ELBStrapiSubnet0 -temp-vpc-ELBStrapiSubnet1 -temp-vpc-ELBStrapiSubnet2 - -{ "Fn::ImportValue": "awseb-e-abcdefghijklmno-AutoScalingGroup" } - -Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ] - -Updating 07 config to accept a parameter From 2175304ac9c0e46eb30de763612dc83fc630b7ed Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 17:57:30 +0100 Subject: [PATCH 14/64] adding FN --- .ebextensions/07-custom-vpc.config | 2 +- todo.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 7381478..d61980a 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: "vpc-003597eb63a0a3efe" + VPCId: { "FN::ImportValue": "temp-vpc-ELBStrapiPublicVPC" } Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" diff --git a/todo.md b/todo.md index 8b57e19..6a583a0 100644 --- a/todo.md +++ b/todo.md @@ -57,3 +57,31 @@ Recreate env with database, check the DB subnets - are they the same as the EC2 Can we use cloudformation functions (imports) in .config files under option_settings? (reference a VPC that already exists?) (https://www.reddit.com/r/aws/comments/a2uoae/is_there_a_way_to_reference_an_elastic_beanstalk/) Yes? Yes but only certain functions: . You cannot use FN::ImportValue to reference a resource in another Cloudformation stack. +Append the stackname to the outputs for the VPC and Subnets + +{ "Fn::ImportValue": "awseb-e-abcdefghijklmno-AutoScalingGroup" } + +Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ] + +Updating 07 config to accept a parameter + + +Append the stackname to the outputs for the VPC and Subnets + +!Sub "${AWS::StackName}-VPCID" + +Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC" +Name: !Sub "${AWS::StackName}-ELBStrapiSubnet0" +Name: !Sub "${AWS::StackName}-ELBStrapiSubnet1" +Name: !Sub "${AWS::StackName}-ELBStrapiSubnet2" + +temp-vpc-ELBStrapiPublicVPC +temp-vpc-ELBStrapiSubnet0 +temp-vpc-ELBStrapiSubnet1 +temp-vpc-ELBStrapiSubnet2 + +{ "Fn::ImportValue": "awseb-e-abcdefghijklmno-AutoScalingGroup" } + +Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ] + +Updating 07 config to accept a parameter From 9c7d447c3239d8c8e81c1b93b6000a593e224967 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 17:59:13 +0100 Subject: [PATCH 15/64] updating subnets --- .ebextensions/07-custom-vpc.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index d61980a..3a08d0c 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: VPCId: { "FN::ImportValue": "temp-vpc-ELBStrapiPublicVPC" } - Subnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" - DBSubnets: "subnet-02cd8f7981ddfe345,subnet-02d9e1338e8d92d09,subnet-0e07d4d35394db524" + Subnets: "subnet-0f4910cd377c4f187,subnet-0136183f008f59786,subnet-0264424902b54d2ca" + DBSubnets: "subnet-0f4910cd377c4f187,subnet-0136183f008f59786,subnet-0264424902b54d2ca" From 581db77d35f4f3160492f0d344d87ad62b9d3f8a Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Wed, 29 Apr 2020 18:00:24 +0100 Subject: [PATCH 16/64] adding new VPC --- .ebextensions/07-custom-vpc.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 3a08d0c..e5eee46 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: { "FN::ImportValue": "temp-vpc-ELBStrapiPublicVPC" } + VPCId: vpc-00a10198acfccc195 Subnets: "subnet-0f4910cd377c4f187,subnet-0136183f008f59786,subnet-0264424902b54d2ca" DBSubnets: "subnet-0f4910cd377c4f187,subnet-0136183f008f59786,subnet-0264424902b54d2ca" From 7bda4fe4ea99f619595db27cc4e38358249530f1 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 03:18:49 +0100 Subject: [PATCH 17/64] updating CF templates --- .cloudformation/02-stack-vpc.yaml | 13 ++++-- .cloudformation/03-stack-rdsinstance.yaml | 53 ++++++++++++++++++----- 2 files changed, 52 insertions(+), 14 deletions(-) diff --git a/.cloudformation/02-stack-vpc.yaml b/.cloudformation/02-stack-vpc.yaml index ef71fb2..938c339 100644 --- a/.cloudformation/02-stack-vpc.yaml +++ b/.cloudformation/02-stack-vpc.yaml @@ -75,19 +75,24 @@ Outputs: Description: The VPC ID. Value: !Ref PublicVPC Export: - Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC" + Name: !Sub "${AWS::StackName}-PublicVPC" + PublicVPCIDDefaultSecurityGroup: + Description: The VPC default security group. + Value: !GetAtt PublicVPC.DefaultSecurityGroup + Export: + Name: !Sub "${AWS::StackName}-PublicVPCIDDefaultSecurityGroup" PublicSubnet0ID: Description: The ID of the subnet. Value: !Ref PublicSubnet0 Export: - Name: !Sub "${AWS::StackName}-ELBStrapiSubnet0" + Name: !Sub "${AWS::StackName}-PublicSubnet0" PublicSubnet1ID: Description: The ID of the subnet. Value: !Ref PublicSubnet1 Export: - Name: !Sub "${AWS::StackName}-ELBStrapiSubnet1" + Name: !Sub "${AWS::StackName}-PublicSubnet1" PublicSubnet2ID: Description: The ID of the subnet. Value: !Ref PublicSubnet2 Export: - Name: !Sub "${AWS::StackName}-ELBStrapiSubnet2" + Name: !Sub "${AWS::StackName}-PublicSubnet2" diff --git a/.cloudformation/03-stack-rdsinstance.yaml b/.cloudformation/03-stack-rdsinstance.yaml index 4826da5..6b1c263 100644 --- a/.cloudformation/03-stack-rdsinstance.yaml +++ b/.cloudformation/03-stack-rdsinstance.yaml @@ -1,13 +1,46 @@ AWSTemplateFormatVersion: 2010-09-09 -Description: RDS and settings for ELB strapi deployment. -Metadata: - +Description: This template creates an RDS database for an ELB environment. + In addition to the database it creates a subnet group for the RDS database, + a security group with Ingress rules only allowing connections to the database. + It uses an existing Public VPC and subnet already created in + another Cloudformation stack. This is public so the database can go out + to the internet. Parameters: - -Mappings: - -Conditions: - + StackName: + Description: The stack name of another CloudFormation template. This is used + to prepend the name of other resources in other templates. + Type: String Resources: - -Outputs: + VPCSecurityGroupIngress: + Type: AWS::EC2::SecurityGroupIngress + Properties: + GroupId: + Fn::ImportValue: !Sub "${StackName}-PublicVPCIDDefaultSecurityGroup" + IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + CidrIp: 0.0.0.0/0 + RDSSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: A subnet group for the RDS instance. + SubnetIds: + - Fn::ImportValue: !Sub "${StackName}-PublicSubnet0" + - Fn::ImportValue: !Sub "${StackName}-PublicSubnet1" + - Fn::ImportValue: !Sub "${StackName}-PublicSubnet2" + rdsDBInstance: + Type: AWS::RDS::DBInstance + Properties: + AllocatedStorage: 5 + AllowMajorVersionUpgrade: false + AutoMinorVersionUpgrade: true + DBInstanceClass: "db.t2.micro" + DBName: postgres + Engine: postgres + EngineVersion: 12.2 + MasterUsername: mainuser + MasterUserPassword: password + PubliclyAccessible: true + VPCSecurityGroups: + - Fn::ImportValue: !Sub "${StackName}-PublicVPCIDDefaultSecurityGroup" + DBSubnetGroupName: !Ref RDSSubnetGroup From 4a497599faea975e97f518aa9ab8ad0d2ccbaf83 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 03:18:56 +0100 Subject: [PATCH 18/64] updating notes --- runningnotes.md | 248 ++++++++++++++++++++++++++++++++++++++++++------ tempnotes.md | 86 ++++++++++++++--- todo.md | 42 ++++---- 3 files changed, 315 insertions(+), 61 deletions(-) diff --git a/runningnotes.md b/runningnotes.md index 15d3906..2a47c34 100644 --- a/runningnotes.md +++ b/runningnotes.md @@ -1,3 +1,45 @@ + +* [Running strapi in different modes](#Runningstrapiindifferentmodes) +* [Strapi documentation](#Strapidocumentation) +* [API Examples using HTTPIE](#APIExamplesusingHTTPIE) + * [Authenticate with the API](#AuthenticatewiththeAPI) + * [Get a Single Content Type](#GetaSingleContentType) + * [Use query parameters to filter for Multiple Content Type](#UsequeryparameterstofilterforMultipleContentType) +* [S3 Upload Addon](#S3UploadAddon) + * [AWS Resources](#AWSResources) + * [Configuration](#Configuration) +* [Fix Version Numbers](#FixVersionNumbers) +* [Strapi in git](#Strapiingit) +* [Cloudformation](#Cloudformation) + * [Creating templates](#Creatingtemplates) + * [Adding resources](#Addingresources) + * [Using parameters](#Usingparameters) + * [Using outputs](#Usingoutputs) + * [Using functions](#Usingfunctions) + * [Examples](#Examples) + * [Short form](#Shortform) + * [Outputs](#Outputs) + * [Referencing other resources internally.](#Referencingotherresourcesinternally.) + * [Pesudeo references](#Pesudeoreferences) + * [Referencing other resources from external templates](#Referencingotherresourcesfromexternaltemplates) + * [Deploy a stack/template](#Deployastacktemplate) + * [Passing in parameters](#Passinginparameters) + * [Tags](#Tags) + * [Updating stack](#Updatingstack) + * [Failure](#Failure) + * [Stacks](#Stacks) + * [Snippets](#Snippets) + * [Deploy a template/stack](#Deployatemplatestack) + * [Destroy a stack](#Destroyastack) +* [Tags](#Tags-1) + * [Cloudformation default tags](#Cloudformationdefaulttags) + + + + # Running notes deocument that the db has to be done from cli arg, but the configs can be done via files. @@ -15,7 +57,7 @@ Tie this in with a cloudformation template + hooking it up Try setting the database name using cloudformation template -## Running strapi in different modes +## Running strapi in different modes You should use development for developing strapi and then deploy it to production. @@ -42,7 +84,7 @@ There is no current plans to allow for this, as well as no plans to move these m Due to the reasons I explained above I am going to mark this as closed but please do feel free to discuss. ``` -## Strapi documentation +## Strapi documentation @@ -54,17 +96,17 @@ You should change the production URL server url in the documentation settings. Edit the file `./extensions/documentation/documentation/1.0.0/full_documentation.json` and change `YOUR_PRODUCTION_SERVER` to the ELB URL of your environment. -## API Examples using HTTPIE +## API Examples using HTTPIE -### Authenticate with the API +### Authenticate with the API `http http://strapi-prod.eu-west-1.elasticbeanstalk.com/auth/local identifier=apiuser password=password` -### Get a Single Content Type +### Get a Single Content Type `http http://strapi-prod.eu-west-1.elasticbeanstalk.com/tests Authorization:"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiaWF0IjoxNTg3ODY3NzQ4LCJleHAiOjE1OTA0NTk3NDh9.McAi1b-F3IT2Mw90652AprEMtknJrW66Aw5FGMBOTj0"` -### Use query parameters to filter for Multiple Content Type +### Use query parameters to filter for Multiple Content Type You can use query parameters to filter requests made to the API. @@ -74,17 +116,17 @@ The syntax is `?field_operator=value`, e.g `?title_contains=test`, after the end `http "http://strapi-prod.eu-west-1.elasticbeanstalk.com/tests?title_contains=test" Authorization:"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwiaXNBZG1pbiI6dHJ1ZSwiaWF0IjoxNTg3ODY3NzMwLCJleHAiOjE1OTA0NTk3MzB9.XXdoZUk_GuOION2KlpeWZ7qwXAoEq9vTlIeD2XTnJxY"` -## S3 Upload Addon +## S3 Upload Addon You should add the `strapi-provider-upload-aws-s3` extension using NPM. Make sure you add the same version of Strapi you are using. `npm i strapi-provider-upload-aws-s3@3.0.0-beta.20` -### AWS Resources +### AWS Resources You should have an S3 bucket with public access, and an AWS account that has a policy to access the bucket. -### Configuration +### Configuration You should create a settings file at `./extensions/upload/config/settings.json`. @@ -136,7 +178,7 @@ if (process.env.NODE_ENV === "production") { } ``` -## Fix Version Numbers +## Fix Version Numbers When using Strapi you should make sure the version numbers for **all** dependencies in `./package.json` are fixed for Strapi modules. You cannot mix and match and upgrade arbitrarily. @@ -163,7 +205,7 @@ An example is: } ``` -## Strapi in git +## Strapi in git To have a strapi project in github you should remove the: @@ -179,11 +221,11 @@ When cloning from the repo you should then do a: You can then run Strapi with `npm run develop` or `NODE_ENV=production npm run start`. -## Cloudformation +## Cloudformation (example of deploying an S3 bucket with static site `index.html`.) -### Creating templates +### Creating templates To create a cloudformation template you should create a `template.yaml`. This yaml file should have at the top: @@ -194,13 +236,13 @@ Description: A simple CloudFormation template Then you should add a `Resources` key and populate this with all the infrastructure you need to provision. -### Adding resources +### Adding resources Documentation for all AWS resources is: . A good approach is to use the GUI to create an object, and then lookup the cloudformation template as you go along. -### Using parameters +### Using parameters @@ -220,11 +262,11 @@ Parameters: Description: Enter t2.micro, m1.small, or m1.large. Default is t2.micro. ``` -### Using outputs +### Using outputs -### Using functions +### Using functions A list of all Cloudformation functions is: . @@ -234,7 +276,11 @@ A list of all Cloudformation functions is: Examples + +##### Select, GetAZs and Ref + +Example of `Fn::Select`, `Fn::GetAZs` and `!Ref`: ```yaml PublicSubnet1: @@ -246,7 +292,90 @@ PublicSubnet1: - Fn::GetAZs: !Ref "AWS::Region" ``` -### Outputs +##### GetAtt + +`Fn::GetAtt` differs from `Ref` in that `!GetAtt` gets an attribute of a resource, whereas `Ref` will reference the actual resource itself. An attribute is a return value of a resource. For example, a VPC resource has a `DefaultSecurityGroup` as an attribute that you can access. + +To see attributes that you can reference with `!GetAtt`, you should check the Cloudformation documentation for the resource in question and look at the "Return Values" header: . + +An example would be using `Fn::GetAtt` to export a return value for some object in a template: + +```yaml +Outputs: + PublicVPCIDDefaultSecurityGroup: + Description: The VPC ID. + Value: !GetAtt PublicVPC.DefaultSecurityGroup + Export: + Name: !Sub "${AWS::StackName}-PublicVPCIDDefaultSecurityGroup" +``` + +Long syntax: `Fn::GetAtt: [ logicalNameOfResource, attributeName ]` + +##### Sub + +A really good resource for Cloudformation functions is: . + +Using `Fn::Sub` allows you to substitue a variable into the string you are trying to create. You might want to substitue an input parameter in for example. + +```yaml +AppDnsRecord: + Type: AWS::Route53::RecordSet + Properties: + HostedZoneId: !ImportValue HostedZone-zone-id + Name: + Fn::Sub: + - "myapp.${HostedZoneName}" + - HostedZoneName: !ImportValue HostedZone-zone-name +``` + +Here we have referenced `${HostedZoneName}` - this is a temporary parameter in the sub command. At this point it does not exist, which is why we create a map which defines this variable as the second argument to Sub. In this example it is using `Fn::ImportValue` to import a resource from another Cloudformation stack. + +As this second argument is a map (denoted by the `:`), we can have multiple key,value pairs. + +```yaml +Name: + Fn::Sub: + - "myapp.${SubDomain}.${HostedZoneName}" + - HostedZoneName: !ImportValue HostedZone-zone-name + SubDomain: !ImportValue HostedZone-subzone-name +``` + +Note here that the second definition of the key, value pair does not have a leading `-`. We don't want to pass another argument to the `Sub` command, rather, we want to define additional key,value pair to be substituted in. + +If our import value name also depended on an input parameter (say our imported value name depeneded on a stack name) we would have to use nested sub functions. In the above example we are simply importing a static import value, the string is hardcoded, if we wanted this to be dynamic, and be populated from an input parameter, then we can use: + +```yaml +Parameters: + Route53StackName: + Type: String + +Resources: + AppDnsRecord: + Type: AWS::Route53::RecordSet + Properties: + HostedZoneName: + Fn::ImportValue: !Sub "${Route53StackName}-zone-name" + Name: + Fn::Sub: + - "myapp.${ZoneName}" + - ZoneName: + Fn::ImportValue: !Sub "${Route53StackName}-zone-name" +``` + +Pay attention to the double indentation after `ZoneName`!. + +We have to use the long form of `Fn::ImportValue` here and not the shorthand - this is a Cloudformation restriction. + +#### Short form + +If you are writing templates in yaml there is a long and shortform available. + +An example for the `Sub` function: + +- Longform `Fn::Sub: String` +- Shortform `!Sub String` + +### Outputs You can use the `Outputs:` header in your Cloudformation templates to specify outputs to be used in other Cloudformation templates. @@ -267,7 +396,7 @@ Outputs: You can refer to these in ELB `./config` files for example - allowing you to dynamically link to other AWS resources in your ELB environment. -### Referencing other resources +### Referencing other resources internally. You can reference other resources in the template. This is useful say if you want to define a VPC and a subnet and reference the VPC from the subnet. @@ -277,17 +406,74 @@ To do this you should use the `!Ref` function: VpcId: !Ref PublicVPC ``` -#### Pesudeo references +Note that this is a special syntax, it doesn't have `Fn::` in the long form and the short form, `!Ref` is actually longer than the long form in this case. + + + +#### Pesudeo references You can also reference certain AWS references: . Examples include `AWS::AccountId` and `AWS::StackName` among others. -### Deploy a stack/template +### Referencing other resources from external templates + +Say we have a Cloudformation template where we have created a VPC: + +```yaml +Outputs: + PublicSubnet0ID: + Description: The ID of the subnet. + Value: !Ref PublicSubnet0 + Export: + Name: !Sub "${AWS::StackName}-PublicSubnet0" +``` + +We want to be able to use this, dynamically, in another template. + +To do this we can use the `Fn::Sub` and `Fn::ImportValue` functions. + +```yaml +Parameters: + StackName: + Description: The stack name of another CloudFormation template. This is used + to prepend the name of other resources in other templates. + Type: String +Resources: + RDSSubnetGroup: + Type: AWS::RDS::DBSubnetGroup + Properties: + DBSubnetGroupDescription: A subnet group for the RDS instance. + SubnetIds: + - Fn::ImportValue: !Sub "${StackName}-PublicSubnet0" + - Fn::ImportValue: !Sub "${StackName}-PublicSubnet1" +``` + +### Deploy a stack/template To deploy, you should run the command: `aws cloudformation deploy --template-file template.yaml --stack-name static-website` -### Tags +### Passing in parameters + +You can define parameters in its own section in a Cloudformation template: + +```yaml +Parameters: + StackName: + Description: The stack name of another CloudFormation template. This is used + to prepend the name of other resources in other templates. + Type: String +``` + +You can set a default value which will be used if no value is passed in. + +To pass values in using the CLI you should use the `--parameter-overrides` argument and pass them in as key=value pairs seperated by a space: + +```bash +--parameter-overrides StackName=temp-vpc +``` + +### Tags When setting tags you can set them on individual resources in the Cloudformation template: @@ -307,13 +493,13 @@ Tags: Alternatively if you have many tags to be shared across all resources you can set them when you use the CLI to deploy: `--tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` -### Updating stack +### Updating stack To update a stack you can use `deploy`. Note that the default behaviour is to create the new resources side by side, then once successful remove the old ones. You may run into errors when updating certain resources (updating a VPC subnet will fail as it has to create the new subnet alongside the existing one). You should remove the old stack by doing `delete-stack` first. `aws cloudformation delete-stack --stack-name temp-vpc --profile admin` -### Failure +### Failure If something goes wrong, you can use `describe-stack-events` and pass the `stack-name` to find the events leading up to the failure: `aws cloudformation describe-stack-events --stack-name strapi-s3`. @@ -321,7 +507,7 @@ If this is the first time you are creating a stack you will not be able to re-de You can delete a stack by running: `aws --profile admin cloudformation delete-stack --stack-name strapi-s3`. -### Stacks +### Stacks @@ -329,9 +515,9 @@ A cloudformation stack is a collection of AWS resources that you can manage as a Using stacks means AWS will treat all resources as a single unit. They must all be created or destroyed successfully to be created or deleted. If a resource cannot be created, Cloudformation will roll the stack back to the previous configuration and delete any interim resources that were created. -### Snippets +### Snippets -#### Deploy a template/stack +#### Deploy a template/stack `aws --profile admin cloudformation deploy --template-file ./01-stack-storage.yaml --stack-name strapi-s3` @@ -339,11 +525,11 @@ You can pass paramter values in with `--paramter-overrides KEY=VALUE`: `--parameter-overrides TestParameter="some test string"` -#### Destroy a stack +#### Destroy a stack `aws --profile admin cloudformation delete-stack --stack-name strapi-s3` -## Tags +## Tags Suggested tags for all AWS resources are: @@ -356,7 +542,7 @@ Suggested tags for all AWS resources are: | environment | environment resource belongs to | `dev`, `prod` | | deployment | AWS tool used for deployment | `cloudformation`, `elb` | -### Cloudformation default tags +### Cloudformation default tags For Cloudformation resources the following tags get applied automatically: diff --git a/tempnotes.md b/tempnotes.md index 31714ed..d256e2f 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -1,6 +1,29 @@ + + +- [Decoupling](#Decoupling) +- [Creating Database + VPC + Subnets in Cloudformation](#CreatingDatabaseVPCSubnetsinCloudformation) +- [Single instance (no load balancer)](#Singleinstancenoloadbalancer) + _ [EC2::VPC](#EC2::VPC) + _ [Enable DNS](#EnableDNS) + _ [EC2::Subnet](#EC2::Subnet) + _ [EC2::InternetGateway](#EC2::InternetGateway) + _ [EC2::VPCGatewayAttachment](#EC2::VPCGatewayAttachment) + _ [AWS::EC2::RouteTable](#AWS::EC2::RouteTable) + _ [AWS::EC2::Route](#AWS::EC2::Route) + _ [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation) +- [Running notes](#Runningnotes) +- [Reference an input parameter, or a resource ID from inside current template](#ReferenceaninputparameteroraresourceIDfrominsidecurrenttemplate) \* [Using `Fn::Sub`](#UsingFn::Sub) +- [Dynamically referencing resources from another stack.](#Dynamicallyreferencingresourcesfromanotherstack.) + + + + # Temp Notes -## Decoupling +## Decoupling When creating an ELB instance with `--single` and `--database` the following is created as part of the ELB deployment: @@ -10,7 +33,7 @@ When creating an ELB instance with `--single` and `--database` the following is Is the security group created without a databse? (probably yes...) -## Creating Database + VPC + Subnets in Cloudformation +## Creating Database + VPC + Subnets in Cloudformation Template from AWS showing cross-stack referencing and creating and referencing a VPC: . @@ -24,7 +47,7 @@ You should use this VPC for you RDS instance. Creating a VPC for ELB (with RDS) -## Single instance (no load balancer) +## Single instance (no load balancer) Example cloudformation template that ELB uses: . @@ -56,13 +79,13 @@ You should then create a public route table and associate it with the VPC you ha You should then create a public route. You can then attach the internet gateway attachment to this route and specify a list of IPs that will go out to the internet. To allow all trafic to the internet set a `DestinationCidrBlock` of `0.0.0.0/0`. -### EC2::VPC +### EC2::VPC -#### Enable DNS +#### Enable DNS Enable `EnableDnsHostnames` + `EnableDnsSupport` - this allows resources in the VPC to use DNS in AWS. -### EC2::Subnet +### EC2::Subnet Go to the EC2 dashboard to find all availability zones. Create a subnet for each zone. @@ -71,33 +94,70 @@ Go to the EC2 dashboard to find all availability zones. Create a subnet for each - `CidrBlock` - `MapPublicIpOnLaunch` -### EC2::InternetGateway +### EC2::InternetGateway -### EC2::VPCGatewayAttachment +### EC2::VPCGatewayAttachment - `VpcId` - `InternetGatewayId` -### AWS::EC2::RouteTable +### AWS::EC2::RouteTable - `VpcId` -### AWS::EC2::Route +### AWS::EC2::Route - `RouteTableId` - `DestinationCidrBlock` - `GatewayId` -### AWS::EC2::SubnetRouteTableAssociation +### AWS::EC2::SubnetRouteTableAssociation - `SubnetId` - `RouteTableId` -## Running notes +## Running notes -If we specify the VPC + Subnets from Cloudformation in a config file, will it create the security groups automatically for the EC2 instances? +If we specify the VPC + Subnets from Cloudformation in a config file, will it create the security groups automatically for the EC2 instances? - Yes Database can use existing subnets. Database needs a security group creating EC2 security groups automatically created and associated with the VPC. Use aws:ec2:vpc (https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/command-options-general.html#command-options-general-ec2vpc) + +### Database + +Needs: + +- `AWS::RDS::DBSubnetGroup` +- `AWS::EC2::SecurityGroupIngress` +- `AWS::RDS::DBInstance` + +Default ports: + +| Database Engine | Default Port | +| -------------------- | ------------ | +| Aurora/MySQL/MariaDB | 3306 | +| PostgreSQL | 5432 | +| Oracle | 1521 | +| SQL Server | 1433 | +| DynamoDB | 8000 | + + + +## Work Commands + +### deploy + +`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name temp-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` + +`aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name temp --parameter-overrides StackName=temp-vpc` + +### delete + +`aws --profile admin cloudformation delete-stack --stack-name temp-vpc` + +`aws --profile admin cloudformation delete-stack --stack-name temp` + +List of all RDS Engines available under "Engine" header: . + diff --git a/todo.md b/todo.md index 6a583a0..d0822c0 100644 --- a/todo.md +++ b/todo.md @@ -57,31 +57,39 @@ Recreate env with database, check the DB subnets - are they the same as the EC2 Can we use cloudformation functions (imports) in .config files under option_settings? (reference a VPC that already exists?) (https://www.reddit.com/r/aws/comments/a2uoae/is_there_a_way_to_reference_an_elastic_beanstalk/) Yes? Yes but only certain functions: . You cannot use FN::ImportValue to reference a resource in another Cloudformation stack. -Append the stackname to the outputs for the VPC and Subnets - -{ "Fn::ImportValue": "awseb-e-abcdefghijklmno-AutoScalingGroup" } - Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ] Updating 07 config to accept a parameter +For DB -Append the stackname to the outputs for the VPC and Subnets +Follow -!Sub "${AWS::StackName}-VPCID" +Create a subnet group (add each subnet to this group) +Create a security Group for DB +Create a SecurityGroupIngress +Use existing public VPC and subnet -Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC" -Name: !Sub "${AWS::StackName}-ELBStrapiSubnet0" -Name: !Sub "${AWS::StackName}-ELBStrapiSubnet1" -Name: !Sub "${AWS::StackName}-ELBStrapiSubnet2" +What is the RDS hostname inside the container? -temp-vpc-ELBStrapiPublicVPC -temp-vpc-ELBStrapiSubnet0 -temp-vpc-ELBStrapiSubnet1 -temp-vpc-ELBStrapiSubnet2 +Follow a naming convention for likewise cloudformation templates -{ "Fn::ImportValue": "awseb-e-abcdefghijklmno-AutoScalingGroup" } +E.g. -Use join for subnets Name: !Join [ ":", [ !Ref "AWS::StackName", AccountVPC ] ] +```yaml +Outputs: + PublicVPCID: + Description: The VPC ID. + Value: !Ref PublicVPC + Export: + Name: !Sub "${AWS::StackName}-ELBStrapiPublicVPC" +``` -Updating 07 config to accept a parameter +Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are). + + +Check if the security group of the CF RDS matches that of ELB RDS. They should specify the same (one postgres inbound on 5432 and all traffic all/all inbound) + +Do we need a seperate security group for the database? - The answer should be that there is a seperate security group for RDS, and one for EC2. EC2 one should be created by ELB automatically. + +Does the db and the ec2 instances share the same VPC? From a8a30715d77c6bb504052526e5d869cd201331a5 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 03:19:02 +0100 Subject: [PATCH 19/64] updating VPC config --- .ebextensions/07-custom-vpc.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index e5eee46..8a1ff21 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: vpc-00a10198acfccc195 - Subnets: "subnet-0f4910cd377c4f187,subnet-0136183f008f59786,subnet-0264424902b54d2ca" - DBSubnets: "subnet-0f4910cd377c4f187,subnet-0136183f008f59786,subnet-0264424902b54d2ca" + VPCId: vpc-099d191f8576a0af4 + Subnets: "subnet-077d92cc78dff958b,subnet-08f41ced458891085,subnet-03d2413d530aa2278" + DBSubnets: "subnet-077d92cc78dff958b,subnet-08f41ced458891085,subnet-03d2413d530aa2278" From a65464e3e84537449ecfc62b97b5005d0146b00c Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 18:10:17 +0100 Subject: [PATCH 20/64] updating RDS CF --- .cloudformation/03-stack-rdsinstance.yaml | 34 +++++++++++++++-------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/.cloudformation/03-stack-rdsinstance.yaml b/.cloudformation/03-stack-rdsinstance.yaml index 6b1c263..9bbfa79 100644 --- a/.cloudformation/03-stack-rdsinstance.yaml +++ b/.cloudformation/03-stack-rdsinstance.yaml @@ -11,15 +11,15 @@ Parameters: to prepend the name of other resources in other templates. Type: String Resources: - VPCSecurityGroupIngress: - Type: AWS::EC2::SecurityGroupIngress - Properties: - GroupId: - Fn::ImportValue: !Sub "${StackName}-PublicVPCIDDefaultSecurityGroup" - IpProtocol: tcp - FromPort: 5432 - ToPort: 5432 - CidrIp: 0.0.0.0/0 + # VPCSecurityGroupIngress: + # Type: AWS::EC2::SecurityGroupIngress + # Properties: + # GroupId: + # Fn::ImportValue: !Sub "${StackName}-PublicVPCIDDefaultSecurityGroup" + # IpProtocol: tcp + # FromPort: 5432 + # ToPort: 5432 + # CidrIp: 0.0.0.0/0 RDSSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: @@ -28,7 +28,19 @@ Resources: - Fn::ImportValue: !Sub "${StackName}-PublicSubnet0" - Fn::ImportValue: !Sub "${StackName}-PublicSubnet1" - Fn::ImportValue: !Sub "${StackName}-PublicSubnet2" - rdsDBInstance: + RDSSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupName: !Sub "${AWS::StackName}-RDS-SecurityGroup" + GroupDescription: Security Group for RDS allowing ingress on DB port only. + VpcId: + Fn::ImportValue: !Sub "${StackName}-PublicVPC" + SecurityGroupIngress: + IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + CidrIp: 0.0.0.0/0 + RDSDBInstance: Type: AWS::RDS::DBInstance Properties: AllocatedStorage: 5 @@ -42,5 +54,5 @@ Resources: MasterUserPassword: password PubliclyAccessible: true VPCSecurityGroups: - - Fn::ImportValue: !Sub "${StackName}-PublicVPCIDDefaultSecurityGroup" + - !Ref RDSSecurityGroup DBSubnetGroupName: !Ref RDSSubnetGroup From d8aadac65e41fb8c72724125309ef8e9a6fdfa1f Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 18:10:29 +0100 Subject: [PATCH 21/64] updating documentation --- jq.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ tempnotes.md | 13 ++++++++-- todo.md | 22 +++++++++++++++- 3 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 jq.md diff --git a/jq.md b/jq.md new file mode 100644 index 0000000..23308d9 --- /dev/null +++ b/jq.md @@ -0,0 +1,72 @@ +# JQ + +## Piping into jq + +You can `cat` or `bat` a file and pipe it into `jq`. + +You can also take a command that returns json and pipe it into `jq`. + +## Returning data without " + +To return data without `jq` wrapping results in `"` use the `-r` flag. + +`jq -r` + +## Filtering + +### Get values from a key + +Running `aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq` returns: + +```json +{ + "StackResources": [ + { + "StackName": "strapi-vpc", + "StackId": "arn:aws:cloudformation:eu-west-1:745437999005:stack/strapi-vpc/a9e41430-8afc-11ea-bdaa-0a736ea8438a", + "LogicalResourceId": "InternetGateway", + "PhysicalResourceId": "igw-0e059db8e0795ac32", + "ResourceType": "AWS::EC2::InternetGateway", + "Timestamp": "2020-04-30T16:07:42.434Z", + "ResourceStatus": "CREATE_COMPLETE", + "DriftInformation": { + "StackResourceDriftStatus": "NOT_CHECKED" + } + }, + { + "StackName": "strapi-vpc", + "StackId": "arn:aws:cloudformation:eu-west-1:745437999005:stack/strapi-vpc/a9e41430-8afc-11ea-bdaa-0a736ea8438a", + "LogicalResourceId": "InternetGatewayAttachment", + "PhysicalResourceId": "strap-Inter-1413K0IDR1L3N", + "ResourceType": "AWS::EC2::VPCGatewayAttachment", + "Timestamp": "2020-04-30T16:08:00.147Z", + "ResourceStatus": "CREATE_COMPLETE", + "DriftInformation": { + "StackResourceDriftStatus": "NOT_CHECKED" + } + }, +``` + +We can then use `jq`'s filtering to return values. + +We have a key of `StackResources` which contains a list: `.StackResources[]` + +We can then pass in the key we want `.StackResources[].PhysicalResourceId` + +`aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq -r '.StackResources[].PhysicalResourceId'` which gives: + +```json +"igw-0e059db8e0795ac32" +"strap-Inter-1413K0IDR1L3N" +"strap-Publi-1TS82BV8W4UFD" +"rtb-0cf8d05f71a30ef03" +"subnet-051fe56dc37d8396d" +"rtbassoc-0f7ae2fbdfe6bf2a5" +"subnet-0ea9f2f165a57be27" +"rtbassoc-00a67937c3778e273" +"subnet-09b28d722f41b2dde" +"rtbassoc-0a0a6bd0f8ff641df" +"vpc-029d232726cbf591d" +``` + +`aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq -r '.StackResources[] | .ResourceType + ": " + .PhysicalResourceId'` diff --git a/tempnotes.md b/tempnotes.md index d256e2f..57c4e51 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -149,15 +149,24 @@ Default ports: ### deploy -`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name temp-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` +`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` -`aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name temp --parameter-overrides StackName=temp-vpc` +`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name new-temp-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` + +`aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name strapi-rds --parameter-overrides StackName=strapi-vpc` ### delete `aws --profile admin cloudformation delete-stack --stack-name temp-vpc` +`aws --profile admin cloudformation delete-stack --stack-name new-temp-vpc` + `aws --profile admin cloudformation delete-stack --stack-name temp` List of all RDS Engines available under "Engine" header: . +### descrive-stack-resources + +Will print a json list of all resources in the stack + +`aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc` diff --git a/todo.md b/todo.md index d0822c0..f11b433 100644 --- a/todo.md +++ b/todo.md @@ -87,9 +87,29 @@ Outputs: Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are). - Check if the security group of the CF RDS matches that of ELB RDS. They should specify the same (one postgres inbound on 5432 and all traffic all/all inbound) +They don't - the traffic all/all isnt there on ELB RDS SG. +This is because we are editing the default security group. We should create a new security group then change the inbound rules on there. Do we need a seperate security group for the database? - The answer should be that there is a seperate security group for RDS, and one for EC2. EC2 one should be created by ELB automatically. Does the db and the ec2 instances share the same VPC? + +To Do + +Change stacknames +New stack names +--stack-name temp-vpc: strapi-vpc-seperate +--stack-name new-temp-vpc: strapi-vpc-elb +--stack-name temp: strapi-elb + +- Create the VPC CF template twice (one for ELB, other to compare) +- In RDS CF template: + - Create a https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html + - Change SecurityGroupIngress to this SG +- Deploy strapi-prod with VPC + subnets of one of the VPCs +- Compare the db SG ingress with ELB, should be the same now. + +- Destroy all above +- Redeploy but only do one VPC, put this in strapi-prod and deploy ELB app with DB +- Redeploy strapi-elb but change the RDS env vars to point to standalone RDS. From 452e6241d8abe569a0a8d8370ab16cf41b315e97 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 18:10:48 +0100 Subject: [PATCH 22/64] updating new subnet --- .ebextensions/07-custom-vpc.config | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 8a1ff21..61f6dd6 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,5 +1,5 @@ option_settings: aws:ec2:vpc: - VPCId: vpc-099d191f8576a0af4 - Subnets: "subnet-077d92cc78dff958b,subnet-08f41ced458891085,subnet-03d2413d530aa2278" - DBSubnets: "subnet-077d92cc78dff958b,subnet-08f41ced458891085,subnet-03d2413d530aa2278" + VPCId: vpc-029d232726cbf591d + Subnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" + DBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" From 150b709e0b92e92d7060e06b17244122190536da Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 18:10:53 +0100 Subject: [PATCH 23/64] updating RDS env vars --- .ebextensions/04-environment.config | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.ebextensions/04-environment.config b/.ebextensions/04-environment.config index b3868d0..0848261 100644 --- a/.ebextensions/04-environment.config +++ b/.ebextensions/04-environment.config @@ -13,3 +13,13 @@ option_settings: value: "eu-west-1" - option_name: STRAPI_S3_BUCKET value: "elb-example-bucket-cf" + - option_name: RDS_HOSTNAME + value: srdtnvn77v7rqd.chgwfe43ss59.eu-west-1.rds.amazonaws.com + - option_name: RDS_PORT + value: 5432 + - option_name: RDS_NAME + value: postgres + - option_name: RDS_USERNAME + value: mainuser + - option_name: RDS_PASSWORD + value: password From 3e88adf79216d0309c2cca221020aaee4145f43a Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 19:05:17 +0100 Subject: [PATCH 24/64] updating docs --- todo.md | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/todo.md b/todo.md index f11b433..8c86186 100644 --- a/todo.md +++ b/todo.md @@ -87,29 +87,25 @@ Outputs: Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are). -Check if the security group of the CF RDS matches that of ELB RDS. They should specify the same (one postgres inbound on 5432 and all traffic all/all inbound) -They don't - the traffic all/all isnt there on ELB RDS SG. -This is because we are editing the default security group. We should create a new security group then change the inbound rules on there. +Do we need a seperate security group for the database? - The answer should be that there is a seperate security group for RDS, and one for EC2. EC2 one should be created by ELB automatically. - This is true. The RDS one is created in CF. -Do we need a seperate security group for the database? - The answer should be that there is a seperate security group for RDS, and one for EC2. EC2 one should be created by ELB automatically. - -Does the db and the ec2 instances share the same VPC? +Does the db and the ec2 instances share the same VPC? - Yes. They have different security groups. To Do -Change stacknames -New stack names ---stack-name temp-vpc: strapi-vpc-seperate ---stack-name new-temp-vpc: strapi-vpc-elb ---stack-name temp: strapi-elb +To have a replica database you should create a new DB instance with same AllocatedStorage size and DBInstanceClass. You should set the SourceDBInstanceIdentifier to be a `!Ref` of your primary DB. You should also set the SourceRegion. -- Create the VPC CF template twice (one for ELB, other to compare) -- In RDS CF template: - - Create a https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-ec2-security-group.html - - Change SecurityGroupIngress to this SG -- Deploy strapi-prod with VPC + subnets of one of the VPCs -- Compare the db SG ingress with ELB, should be the same now. +CF RDS ELB template: +https://github.com/garystafford/aws-rds-postgres/blob/master/cfn-templates/rds.template -- Destroy all above -- Redeploy but only do one VPC, put this in strapi-prod and deploy ELB app with DB -- Redeploy strapi-elb but change the RDS env vars to point to standalone RDS. +Read replica CF docs: +https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#cfn-rds-dbinstance-sourcedbinstanceidentifier + +Doc the CF changes for both +Combine them into a single CF stack +Deploy + +Deploy strapi with LB + scaling +Enable HTTPS + +Codebuild From 67951f21f417dfe9deb19b61904c20a1a0e395fa Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 19:05:40 +0100 Subject: [PATCH 25/64] changing ip to home only --- .cloudformation/03-stack-rdsinstance.yaml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/.cloudformation/03-stack-rdsinstance.yaml b/.cloudformation/03-stack-rdsinstance.yaml index 9bbfa79..f0b5187 100644 --- a/.cloudformation/03-stack-rdsinstance.yaml +++ b/.cloudformation/03-stack-rdsinstance.yaml @@ -11,15 +11,6 @@ Parameters: to prepend the name of other resources in other templates. Type: String Resources: - # VPCSecurityGroupIngress: - # Type: AWS::EC2::SecurityGroupIngress - # Properties: - # GroupId: - # Fn::ImportValue: !Sub "${StackName}-PublicVPCIDDefaultSecurityGroup" - # IpProtocol: tcp - # FromPort: 5432 - # ToPort: 5432 - # CidrIp: 0.0.0.0/0 RDSSubnetGroup: Type: AWS::RDS::DBSubnetGroup Properties: @@ -39,7 +30,7 @@ Resources: IpProtocol: tcp FromPort: 5432 ToPort: 5432 - CidrIp: 0.0.0.0/0 + CidrIp: 82.6.205.148 RDSDBInstance: Type: AWS::RDS::DBInstance Properties: From b60bebbddcecca071bd6caf0ad68d36bca73b8ec Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 19:47:15 +0100 Subject: [PATCH 26/64] adding custom securitygroup to deployment --- .ebextensions/07-custom-vpc.config | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 61f6dd6..60c78ad 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -3,3 +3,5 @@ option_settings: VPCId: vpc-029d232726cbf591d Subnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" DBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" + aws:autoscaling:launchconfiguration: + SecurityGroups: sg-0d339673ef68988a4 From bea77bf9fa51d8e96e59f0ff3a1ffe7687eb5e04 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 23:55:10 +0100 Subject: [PATCH 27/64] adding VPC to ELB config --- .ebextensions/01-strapi-assets-s3.config | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.ebextensions/01-strapi-assets-s3.config b/.ebextensions/01-strapi-assets-s3.config index e69de29..be19125 100644 --- a/.ebextensions/01-strapi-assets-s3.config +++ b/.ebextensions/01-strapi-assets-s3.config @@ -0,0 +1,6 @@ +Resources: + ElasticLoadBalancer: + Type: AWS::ElasticLoadBalancingV2::TargetGroup + Properties: + VpcId: vpc-029d232726cbf591d + From 31936a672939029368c543e035cd413219d79b86 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 23:55:16 +0100 Subject: [PATCH 28/64] commenting out single instance --- .ebextensions/03-general-options.config | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.ebextensions/03-general-options.config b/.ebextensions/03-general-options.config index aecd348..776cfb2 100644 --- a/.ebextensions/03-general-options.config +++ b/.ebextensions/03-general-options.config @@ -1,6 +1,6 @@ option_settings: - aws:elasticbeanstalk:environment: - EnvironmentType: SingleInstance + # aws:elasticbeanstalk:environment: + # EnvironmentType: SingleInstance aws:rds:dbinstance: DBEngine: postgres DBInstanceClass: "db.t2.micro" From ea12dc3827d2dcb390a29be9983a2b77c4b87306 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 23:55:24 +0100 Subject: [PATCH 29/64] updating CF templates --- .cloudformation/02-stack-vpc.yaml | 14 ++++++++++++++ .cloudformation/03-stack-rdsinstance.yaml | 13 +++++++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/.cloudformation/02-stack-vpc.yaml b/.cloudformation/02-stack-vpc.yaml index 938c339..9a77ba8 100644 --- a/.cloudformation/02-stack-vpc.yaml +++ b/.cloudformation/02-stack-vpc.yaml @@ -7,6 +7,15 @@ Resources: CidrBlock: "172.31.0.0/16" EnableDnsHostnames: true EnableDnsSupport: true + PublicSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupName: !Sub "${AWS::StackName}-PublicSecurityGroup" + GroupDescription: Security group for the EC2 instances. This group does + not set any ingress/egress permissions as Elastic Beanstalk will create + these for us. This group will be attached to our EC2 instances, and the + RDS instance will permit incoming traffic from this group only. + VpcId: !Ref PublicVPC PublicSubnet0: Type: AWS::EC2::Subnet Properties: @@ -76,6 +85,11 @@ Outputs: Value: !Ref PublicVPC Export: Name: !Sub "${AWS::StackName}-PublicVPC" + PublicSecurityGroupId: + Description: The EC2 security group ID. + Value: !Ref PublicSecurityGroup + Export: + Name: !Sub "${AWS::StackName}-PublicSecurityGroup" PublicVPCIDDefaultSecurityGroup: Description: The VPC default security group. Value: !GetAtt PublicVPC.DefaultSecurityGroup diff --git a/.cloudformation/03-stack-rdsinstance.yaml b/.cloudformation/03-stack-rdsinstance.yaml index f0b5187..af42ca0 100644 --- a/.cloudformation/03-stack-rdsinstance.yaml +++ b/.cloudformation/03-stack-rdsinstance.yaml @@ -27,10 +27,15 @@ Resources: VpcId: Fn::ImportValue: !Sub "${StackName}-PublicVPC" SecurityGroupIngress: - IpProtocol: tcp - FromPort: 5432 - ToPort: 5432 - CidrIp: 82.6.205.148 + - IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + CidrIp: 82.6.205.148/32 + - IpProtocol: tcp + FromPort: 5432 + ToPort: 5432 + SourceSecurityGroupId: + Fn::ImportValue: !Sub "${StackName}-PublicSecurityGroup" RDSDBInstance: Type: AWS::RDS::DBInstance Properties: From c1e515d28b37519e04b79b038842e51f0758e5d5 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Thu, 30 Apr 2020 23:55:29 +0100 Subject: [PATCH 30/64] updating notes --- tempnotes.md | 4 ++++ todo.md | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/tempnotes.md b/tempnotes.md index 57c4e51..da25ec4 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -147,6 +147,10 @@ Default ports: ## Work Commands +### tags + +`--tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` + ### deploy `aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` diff --git a/todo.md b/todo.md index 8c86186..be3687b 100644 --- a/todo.md +++ b/todo.md @@ -109,3 +109,11 @@ Deploy strapi with LB + scaling Enable HTTPS Codebuild + +Create the security group for the EC2 instances +Add this security group to Outputs +Reference it in RDS security group + +Check ssh? - Can ssh if you apply it to the EC2 SG you create. + +Multiple security groups get squashed to determine what is and isn't allowed: . From 008aa708bff45cf6ff7040a965008d2008bbc8e9 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 00:02:19 +0100 Subject: [PATCH 31/64] commenting out ELB config --- .ebextensions/01-strapi-assets-s3.config | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/.ebextensions/01-strapi-assets-s3.config b/.ebextensions/01-strapi-assets-s3.config index be19125..3b2e399 100644 --- a/.ebextensions/01-strapi-assets-s3.config +++ b/.ebextensions/01-strapi-assets-s3.config @@ -1,6 +1,5 @@ -Resources: - ElasticLoadBalancer: - Type: AWS::ElasticLoadBalancingV2::TargetGroup - Properties: - VpcId: vpc-029d232726cbf591d - +# Resources: +# ElasticLoadBalancer: +# Type: AWS::ElasticLoadBalancingV2::TargetGroup +# Properties: +# VpcId: vpc-029d232726cbf591d From 9ba7de1ad2ad42af5b7590050d7dc3f26c63aa3e Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 00:02:26 +0100 Subject: [PATCH 32/64] adding ELB subnets --- .ebextensions/07-custom-vpc.config | 1 + 1 file changed, 1 insertion(+) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 60c78ad..0e5625b 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -3,5 +3,6 @@ option_settings: VPCId: vpc-029d232726cbf591d Subnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" DBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" + ELBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" aws:autoscaling:launchconfiguration: SecurityGroups: sg-0d339673ef68988a4 From 3fc49078ab2ab94efe47de285267a074e22f88dc Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 01:48:07 +0100 Subject: [PATCH 33/64] changing minsize to 2 --- .ebextensions/07-custom-vpc.config | 2 ++ tempnotes.md | 18 +++++++++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 0e5625b..05a51ba 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -6,3 +6,5 @@ option_settings: ELBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" aws:autoscaling:launchconfiguration: SecurityGroups: sg-0d339673ef68988a4 + aws:autoscaling:asg: + MinSize: 2 diff --git a/tempnotes.md b/tempnotes.md index da25ec4..46f69bc 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -143,8 +143,6 @@ Default ports: | SQL Server | 1433 | | DynamoDB | 8000 | - - ## Work Commands ### tags @@ -169,8 +167,22 @@ Default ports: List of all RDS Engines available under "Engine" header: . -### descrive-stack-resources +### describe-stack-resources Will print a json list of all resources in the stack `aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc` + +Using `jq` for formatting: + +`aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq -r '.StackResources[] | .ResourceType + ": " + .PhysicalResourceId'` + +Good repo for examples: + +Doc: +Add the ELB subnets to the VPC config + +Create another custom security group for the EC2 instance - should be private +autoscaling should have current public security group + +Load balancer should have the current subnets From c97321790b2528df98b685be113d78bcc8ed5f70 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 02:59:59 +0100 Subject: [PATCH 34/64] working config --- .ebextensions/03-general-options.config | 10 +++++----- .ebextensions/07-custom-vpc.config | 3 ++- tempnotes.md | 18 ++++++++++++++++++ todo.md | 8 ++++++++ 4 files changed, 33 insertions(+), 6 deletions(-) diff --git a/.ebextensions/03-general-options.config b/.ebextensions/03-general-options.config index 776cfb2..b9d3c91 100644 --- a/.ebextensions/03-general-options.config +++ b/.ebextensions/03-general-options.config @@ -1,10 +1,10 @@ option_settings: # aws:elasticbeanstalk:environment: # EnvironmentType: SingleInstance - aws:rds:dbinstance: - DBEngine: postgres - DBInstanceClass: "db.t2.micro" - DBAllocatedStorage: 5 - DBUser: strapi + # aws:rds:dbinstance: + # DBEngine: postgres + # DBInstanceClass: "db.t2.micro" + # DBAllocatedStorage: 5 + # DBUser: strapi aws:ec2:instances: InstanceTypes: "t2.micro" diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 05a51ba..1b31a42 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -7,4 +7,5 @@ option_settings: aws:autoscaling:launchconfiguration: SecurityGroups: sg-0d339673ef68988a4 aws:autoscaling:asg: - MinSize: 2 + MinSize: 1 + MaxSize: 2 diff --git a/tempnotes.md b/tempnotes.md index 46f69bc..e332208 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -186,3 +186,21 @@ Create another custom security group for the EC2 instance - should be private autoscaling should have current public security group Load balancer should have the current subnets + +Loadbalancer security group should have inbound + outbound to 80+443 on 0.0.0.0/0 + +The option_settings: aws:elbv2:loadbalancer has two options for security groups + +ManagedSecurityGroup - defines the security group that is used for the load balancer itself. +SecurityGroups - is a list of additional security groups you want to attach. + +If you define a ManagedSecurityGroup you should set SecurityGroups as well to the same one. + +Load balancer needs a security group that allows incoming 80 + 443 from anywhere +It should also set the same for outbound as well + +This security group should be set in `aws:elbv2:loadbalancer` under +`ManagedSecurityGroup` and `SecurityGroups` + +Additional security groups (in addition to the default one created by ELB) for the EC2 instances are defined in `aws:autoscaling:launchconfiguration` under `SecurityGroups` +A security group will be created for you. You can ammend this (add 443 for https for example) by using `.config` file and creating a `AWS::EC2::SecurityGroupIngress` resource. (see 06-https.config) diff --git a/todo.md b/todo.md index be3687b..80741be 100644 --- a/todo.md +++ b/todo.md @@ -114,6 +114,14 @@ Create the security group for the EC2 instances Add this security group to Outputs Reference it in RDS security group +Summarise the VPC creation - VPC is created, internet gateway is created (and route table) and is added to the VPC for internet access. Controlling what can and cannot go in/out to the internet is done with security groups. + Check ssh? - Can ssh if you apply it to the EC2 SG you create. Multiple security groups get squashed to determine what is and isn't allowed: . + +Show how to create private + public subnets as in . You need a nat gateway to allow private subnets to go out to the internet, but back in. How is this different to using security groups? + +If you use private subnets, the nat gateway is not cheap - £30 a month. You dont need the nat gateway, you can achieve the same thing with security groups (block all incoming) (explained ). Advantage to NAT is all outgoing requests to the internet come from a single IP. + +Summarise the flow -> VPC, internet gateway, attachment + route tables, subnets etc. Mention the nat gateway but show how it can be replaced with security groups. From aaae5360032a08e3385fbb28207e1ef6c80b5292 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 19:44:14 +0100 Subject: [PATCH 35/64] updating VPC CF template --- .cloudformation/02-stack-vpc.yaml | 103 ++++++++++++++++++++++++------ 1 file changed, 85 insertions(+), 18 deletions(-) diff --git a/.cloudformation/02-stack-vpc.yaml b/.cloudformation/02-stack-vpc.yaml index 9a77ba8..242c301 100644 --- a/.cloudformation/02-stack-vpc.yaml +++ b/.cloudformation/02-stack-vpc.yaml @@ -7,15 +7,77 @@ Resources: CidrBlock: "172.31.0.0/16" EnableDnsHostnames: true EnableDnsSupport: true - PublicSecurityGroup: + ELBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: - GroupName: !Sub "${AWS::StackName}-PublicSecurityGroup" - GroupDescription: Security group for the EC2 instances. This group does - not set any ingress/egress permissions as Elastic Beanstalk will create - these for us. This group will be attached to our EC2 instances, and the - RDS instance will permit incoming traffic from this group only. + GroupName: !Sub "${AWS::StackName}-ELBSecurityGroup" + GroupDescription: Security group for the Elastic Load Balancer. + This permits inbound 80/443 from any IP, to 80/443 to the + Auto Scaling security group. VpcId: !Ref PublicVPC + ELBSecurityGroupIngressHttp: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: Ingress for ELBSecurityGroup for HTTP. + GroupId: !Ref ELBSecurityGroup + IpProtocol: tcp + FromPort: 80 + ToPort: 80 + CidrIp: 0.0.0.0/0 + ELBSecurityGroupIngressHttps: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: Ingress for ELBSecurityGroup for HTTPS. + GroupId: !Ref ELBSecurityGroup + IpProtocol: tcp + FromPort: 443 + ToPort: 443 + CidrIp: 0.0.0.0/0 + ELBSecurityGroupEgressHttp: + Type: AWS::EC2::SecurityGroupEgress + Properties: + Description: Egress for ELBSecurityGroup for HTTP. + GroupId: !Ref ELBSecurityGroup + IpProtocol: tcp + FromPort: 80 + ToPort: 80 + SourceSecurityGroupId: !Ref ASSecurityGroup + ELBSecurityGroupEgressHttps: + Type: AWS::EC2::SecurityGroupEgress + Properties: + Description: Egress for ELBSecurityGroup for HTTPS. + GroupId: !Ref ELBSecurityGroup + IpProtocol: tcp + FromPort: 443 + ToPort: 443 + SourceSecurityGroupId: !Ref ASSecurityGroup + ASSecurityGroup: + Type: AWS::EC2::SecurityGroup + Properties: + GroupName: !Sub "${AWS::StackName}-ASSecurityGroup" + GroupDescription: Security group for the Auto Scaler. This security group + will be applied to any EC2 instances that the Auto Scaler creates. This + group permits inbound 80/443 from the Elastic Load Balancer security + group. + VpcId: !Ref PublicVPC + ASSecurityGroupIngressHttp: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: Ingress for ASSecurityGroup for HTTP. + GroupId: !Ref ASSecurityGroup + IpProtocol: tcp + FromPort: 80 + ToPort: 80 + SourceSecurityGroupId: !Ref ELBSecurityGroup + ASSecurityGroupIngressHttps: + Type: AWS::EC2::SecurityGroupIngress + Properties: + Description: Ingress for ASSecurityGroup for HTTPS. + GroupId: !Ref ASSecurityGroup + IpProtocol: tcp + FromPort: 443 + ToPort: 443 + SourceSecurityGroupId: !Ref ELBSecurityGroup PublicSubnet0: Type: AWS::EC2::Subnet Properties: @@ -81,32 +143,37 @@ Resources: RouteTableId: !Ref PublicRouteTable Outputs: PublicVPCID: - Description: The VPC ID. + Description: The VPC for the environment. Value: !Ref PublicVPC Export: Name: !Sub "${AWS::StackName}-PublicVPC" - PublicSecurityGroupId: - Description: The EC2 security group ID. - Value: !Ref PublicSecurityGroup + ELBSecurityGroupOutput: + Description: ELB Security Group + Value: !Ref ELBSecurityGroup Export: - Name: !Sub "${AWS::StackName}-PublicSecurityGroup" - PublicVPCIDDefaultSecurityGroup: - Description: The VPC default security group. - Value: !GetAtt PublicVPC.DefaultSecurityGroup + Name: !Sub "${AWS::StackName}-ELBSecurityGroup" + ASSecurityGroupOutput: + Description: AS Security Group + Value: !Ref ASSecurityGroup Export: - Name: !Sub "${AWS::StackName}-PublicVPCIDDefaultSecurityGroup" + Name: !Sub "${AWS::StackName}-ASSecurityGroup" + # PublicVPCIDDefaultSecurityGroup: + # Description: The VPC default security group. + # Value: !GetAtt PublicVPC.DefaultSecurityGroup + # Export: + # Name: !Sub "${AWS::StackName}-PublicVPCIDDefaultSecurityGroup" PublicSubnet0ID: - Description: The ID of the subnet. + Description: The public subnet 0. Value: !Ref PublicSubnet0 Export: Name: !Sub "${AWS::StackName}-PublicSubnet0" PublicSubnet1ID: - Description: The ID of the subnet. + Description: The public subnet 1. Value: !Ref PublicSubnet1 Export: Name: !Sub "${AWS::StackName}-PublicSubnet1" PublicSubnet2ID: - Description: The ID of the subnet. + Description: The public subnet 2. Value: !Ref PublicSubnet2 Export: Name: !Sub "${AWS::StackName}-PublicSubnet2" From 16058e296da59dc9be2b7fa479279f17d6fcb356 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 19:44:21 +0100 Subject: [PATCH 36/64] updating notes --- tempnotes.md | 14 +++++++++----- todo.md | 2 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tempnotes.md b/tempnotes.md index e332208..d34423d 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -153,15 +153,13 @@ Default ports: `aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` -`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name new-temp-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` - -`aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name strapi-rds --parameter-overrides StackName=strapi-vpc` +`aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name strapi-rds --parameter-overrides StackName=strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` ### delete -`aws --profile admin cloudformation delete-stack --stack-name temp-vpc` +`aws --profile admin cloudformation delete-stack --stack-name strapi-vpc` -`aws --profile admin cloudformation delete-stack --stack-name new-temp-vpc` +`aws --profile admin cloudformation delete-stack --stack-name strapi-rds` `aws --profile admin cloudformation delete-stack --stack-name temp` @@ -204,3 +202,9 @@ This security group should be set in `aws:elbv2:loadbalancer` under Additional security groups (in addition to the default one created by ELB) for the EC2 instances are defined in `aws:autoscaling:launchconfiguration` under `SecurityGroups` A security group will be created for you. You can ammend this (add 443 for https for example) by using `.config` file and creating a `AWS::EC2::SecurityGroupIngress` resource. (see 06-https.config) + +Security group rule to allow instances in the same security group to talk to one another: . + +LB SG: inbound/outbound 80/443 0.0.0.0/0 +Scaling SG: inbound 80/443 from LBSG +DB SG: inbound 5432 from Scaling SG + home ip diff --git a/todo.md b/todo.md index 80741be..ad911bf 100644 --- a/todo.md +++ b/todo.md @@ -125,3 +125,5 @@ Show how to create private + public subnets as in ). Advantage to NAT is all outgoing requests to the internet come from a single IP. Summarise the flow -> VPC, internet gateway, attachment + route tables, subnets etc. Mention the nat gateway but show how it can be replaced with security groups. + +Merge the CF templates into one, make sure all the importing and other s nippets are documented. From f5a5dc44106f1769662b93f919f5053f6336ecc1 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 19:44:26 +0100 Subject: [PATCH 37/64] updating VPC config --- .ebextensions/07-custom-vpc.config | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 1b31a42..3b378bd 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,11 +1,14 @@ option_settings: aws:ec2:vpc: - VPCId: vpc-029d232726cbf591d - Subnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" - DBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" - ELBSubnets: "subnet-051fe56dc37d8396d,subnet-0ea9f2f165a57be27,subnet-09b28d722f41b2dde" + VPCId: vpc-07df912622bfdc48a + Subnets: "subnet-03c544d77a48b38fa,subnet-0751a04eea405768f,subnet-0d68cb85c21c13de1" + DBSubnets: "subnet-03c544d77a48b38fa,subnet-0751a04eea405768f,subnet-0d68cb85c21c13de1" + ELBSubnets: "subnet-03c544d77a48b38fa,subnet-0751a04eea405768f,subnet-0d68cb85c21c13de1" aws:autoscaling:launchconfiguration: - SecurityGroups: sg-0d339673ef68988a4 + SecurityGroups: sg-059ede4dab74687be + aws:elbv2:loadbalancer: + ManagedSecurityGroup: sg-03c3f52febaffb517 + SecurityGroups: sg-03c3f52febaffb517 aws:autoscaling:asg: MinSize: 1 - MaxSize: 2 + MaxSize: 4 From 3d58f2c5d6b3656df64765377eef0f8b90a8d5d6 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 19:59:30 +0100 Subject: [PATCH 38/64] updating RDS env var --- .ebextensions/04-environment.config | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.ebextensions/04-environment.config b/.ebextensions/04-environment.config index 0848261..b318c7a 100644 --- a/.ebextensions/04-environment.config +++ b/.ebextensions/04-environment.config @@ -14,7 +14,7 @@ option_settings: - option_name: STRAPI_S3_BUCKET value: "elb-example-bucket-cf" - option_name: RDS_HOSTNAME - value: srdtnvn77v7rqd.chgwfe43ss59.eu-west-1.rds.amazonaws.com + value: src2ziuj8oxjct.chgwfe43ss59.eu-west-1.rds.amazonaws.com - option_name: RDS_PORT value: 5432 - option_name: RDS_NAME From ab6d220f8c42446d1c650c6abbdbe0f911f791e7 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 19:59:44 +0100 Subject: [PATCH 39/64] updating RDS CF template --- .cloudformation/03-stack-rdsinstance.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.cloudformation/03-stack-rdsinstance.yaml b/.cloudformation/03-stack-rdsinstance.yaml index af42ca0..7a6d758 100644 --- a/.cloudformation/03-stack-rdsinstance.yaml +++ b/.cloudformation/03-stack-rdsinstance.yaml @@ -35,7 +35,7 @@ Resources: FromPort: 5432 ToPort: 5432 SourceSecurityGroupId: - Fn::ImportValue: !Sub "${StackName}-PublicSecurityGroup" + Fn::ImportValue: !Sub "${StackName}-ASSecurityGroup" RDSDBInstance: Type: AWS::RDS::DBInstance Properties: From 2281dd34fd012b435d926d22a1983d5ff7fc1783 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Fri, 1 May 2020 19:59:58 +0100 Subject: [PATCH 40/64] removing default security group config --- .../06-https-instance-securitygroup.config | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/.ebextensions/06-https-instance-securitygroup.config b/.ebextensions/06-https-instance-securitygroup.config index e32bd94..2ef29b9 100644 --- a/.ebextensions/06-https-instance-securitygroup.config +++ b/.ebextensions/06-https-instance-securitygroup.config @@ -1,9 +1,9 @@ -Resources: - sslSecurityGroupIngress: - Type: AWS::EC2::SecurityGroupIngress - Properties: - GroupId: { "Fn::GetAtt": ["AWSEBSecurityGroup", "GroupId"] } - IpProtocol: tcp - ToPort: 443 - FromPort: 443 - CidrIp: 0.0.0.0/0 +# Resources: +# sslSecurityGroupIngress: +# Type: AWS::EC2::SecurityGroupIngress +# Properties: +# GroupId: { "Fn::GetAtt": ["AWSEBSecurityGroup", "GroupId"] } +# IpProtocol: tcp +# ToPort: 443 +# FromPort: 443 +# CidrIp: 0.0.0.0/0 From 12a967b92e0480b4c705bde6cf28fe7cf2837836 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Sat, 2 May 2020 02:56:18 +0100 Subject: [PATCH 41/64] adding https strapi.panaetius.co.uk --- .ebextensions/08-loadbalancer.config | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .ebextensions/08-loadbalancer.config diff --git a/.ebextensions/08-loadbalancer.config b/.ebextensions/08-loadbalancer.config new file mode 100644 index 0000000..eddad7d --- /dev/null +++ b/.ebextensions/08-loadbalancer.config @@ -0,0 +1,4 @@ +option_settings: + aws:elbv2:listener:443: + Protocol: HTTPS + SSLCertificateArns: arn:aws:acm:eu-west-1:745437999005:certificate/218876af-7f8d-4022-97af-ad982aa540bc From 331643fbf7bf92e7403c95565ca6b95f52f51b0e Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Sat, 2 May 2020 02:56:24 +0100 Subject: [PATCH 42/64] updating docs --- tempnotes.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tempnotes.md b/tempnotes.md index d34423d..3928829 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -151,7 +151,7 @@ Default ports: ### deploy -`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` +`aws --profile admin cloudformation deploy --template-file ./02-stack-vpc.yaml --stack-name strapi-vpc --taws:elbv2:listener:defaultags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` `aws --profile admin cloudformation deploy --template-file ./03-stack-rdsinstance.yaml --stack-name strapi-rds --parameter-overrides StackName=strapi-vpc --tags git=web-dev owner=home project=strapi-elb test=true deployment=cloudformation` @@ -175,6 +175,13 @@ Using `jq` for formatting: `aws --profile admin cloudformation describe-stack-resources --stack-name strapi-vpc | jq -r '.StackResources[] | .ResourceType + ": " + .PhysicalResourceId'` +## Adding SSL to ELB + +### With load balancer + +- Generate the SSL cert in Certificate Manager for your domain +- Configure the load balancer listener + Good repo for examples: Doc: From bae738ad98badc43fd19163de1f8c2ef50bce463 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Sat, 2 May 2020 23:21:07 +0100 Subject: [PATCH 43/64] updating VPC config --- .ebextensions/07-custom-vpc.config | 14 +++++++------- tempnotes.md | 16 ++++++++++++++-- todo.md | 13 +++++++------ 3 files changed, 28 insertions(+), 15 deletions(-) diff --git a/.ebextensions/07-custom-vpc.config b/.ebextensions/07-custom-vpc.config index 3b378bd..16a7580 100644 --- a/.ebextensions/07-custom-vpc.config +++ b/.ebextensions/07-custom-vpc.config @@ -1,14 +1,14 @@ option_settings: aws:ec2:vpc: - VPCId: vpc-07df912622bfdc48a - Subnets: "subnet-03c544d77a48b38fa,subnet-0751a04eea405768f,subnet-0d68cb85c21c13de1" - DBSubnets: "subnet-03c544d77a48b38fa,subnet-0751a04eea405768f,subnet-0d68cb85c21c13de1" - ELBSubnets: "subnet-03c544d77a48b38fa,subnet-0751a04eea405768f,subnet-0d68cb85c21c13de1" + VPCId: vpc-02f98fa754899162c + Subnets: "subnet-0b17872a2b9315fad,subnet-0342e8a0a77b30e23,subnet-0eacb84d238279a58" + DBSubnets: "subnet-0b17872a2b9315fad,subnet-0342e8a0a77b30e23,subnet-0eacb84d238279a58" + ELBSubnets: "subnet-0b17872a2b9315fad,subnet-0342e8a0a77b30e23,subnet-0eacb84d238279a58" aws:autoscaling:launchconfiguration: - SecurityGroups: sg-059ede4dab74687be + SecurityGroups: sg-07a97fc88ba143f26 aws:elbv2:loadbalancer: - ManagedSecurityGroup: sg-03c3f52febaffb517 - SecurityGroups: sg-03c3f52febaffb517 + ManagedSecurityGroup: sg-0e6f91df2ed07050a + SecurityGroups: sg-0e6f91df2ed07050a aws:autoscaling:asg: MinSize: 1 MaxSize: 4 diff --git a/tempnotes.md b/tempnotes.md index 3928829..285adbb 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -177,10 +177,22 @@ Using `jq` for formatting: ## Adding SSL to ELB +You should generate an SSL Certificate in Certificate Manager for your domain. To do this you will need to create a CNAME record to verify you have access to the DNS settings. + +At the same time you should create a CNAME record that maps your subdomain () to the DNS name AWS has given your load balancer (). + ### With load balancer -- Generate the SSL cert in Certificate Manager for your domain -- Configure the load balancer listener +A load balancer is not free! It costs ~£15 a month. + +- Configure the load balancer listener in a EB `.config` file: + +```yaml +option_settings: + aws:elbv2:listener:443: + Protocol: HTTPS + SSLCertificateArns: arn:aws:acm:eu-west-1:745437999005:certificate/218876af-7f8d-4022-97af-ad982aa540bc +``` Good repo for examples: diff --git a/todo.md b/todo.md index ad911bf..f256659 100644 --- a/todo.md +++ b/todo.md @@ -110,14 +110,8 @@ Enable HTTPS Codebuild -Create the security group for the EC2 instances -Add this security group to Outputs -Reference it in RDS security group - Summarise the VPC creation - VPC is created, internet gateway is created (and route table) and is added to the VPC for internet access. Controlling what can and cannot go in/out to the internet is done with security groups. -Check ssh? - Can ssh if you apply it to the EC2 SG you create. - Multiple security groups get squashed to determine what is and isn't allowed: . Show how to create private + public subnets as in . You need a nat gateway to allow private subnets to go out to the internet, but back in. How is this different to using security groups? @@ -127,3 +121,10 @@ If you use private subnets, the nat gateway is not cheap - £30 a month. You don Summarise the flow -> VPC, internet gateway, attachment + route tables, subnets etc. Mention the nat gateway but show how it can be replaced with security groups. Merge the CF templates into one, make sure all the importing and other s nippets are documented. + + +- Sort this page + documentation out +- Change ELB to EB +- Once documented and happy, create single CF Template +- Create single instance deployment + https (document) +- Terraform it all up From b16b7474146729ae64d75da0334af4da834a0ea6 Mon Sep 17 00:00:00 2001 From: dtomlinson Date: Sun, 3 May 2020 00:23:34 +0100 Subject: [PATCH 44/64] updating documentation --- runningnotes.md | 18 ++++++ tempnotes.md | 165 +++++++++++++++++++++++++++++++++++------------- todo.md | 125 ++---------------------------------- 3 files changed, 146 insertions(+), 162 deletions(-) diff --git a/runningnotes.md b/runningnotes.md index 2a47c34..ce2cf62 100644 --- a/runningnotes.md +++ b/runningnotes.md @@ -11,6 +11,7 @@ * [Fix Version Numbers](#FixVersionNumbers) * [Strapi in git](#Strapiingit) * [Cloudformation](#Cloudformation) + * [Output naming convention](#Outputnamingconvention) * [Creating templates](#Creatingtemplates) * [Adding resources](#Addingresources) * [Using parameters](#Usingparameters) @@ -225,6 +226,23 @@ You can then run Strapi with `npm run develop` or `NODE_ENV=production npm run s (example of deploying an S3 bucket with static site `index.html`.) +### Output naming convention + +You should follow a standard naming convention for your CF outputs. + +For example: + +```yaml +Outputs: + PublicVPCOutput: + Description: The VPC ID. + Value: !Ref PublicVPC + Export: + Name: !Sub "${AWS::StackName}-EBStrapiPublicVPC" +``` + +Defines a VPC. We can then pass in the stackname to another CF template and it can reference this VPC. The VPC names are static between projects (they don't have to be but here they are). + ### Creating templates To create a cloudformation template you should create a `template.yaml`. This yaml file should have at the top: diff --git a/tempnotes.md b/tempnotes.md index 285adbb..4279029 100644 --- a/tempnotes.md +++ b/tempnotes.md @@ -1,19 +1,35 @@ - -- [Decoupling](#Decoupling) -- [Creating Database + VPC + Subnets in Cloudformation](#CreatingDatabaseVPCSubnetsinCloudformation) -- [Single instance (no load balancer)](#Singleinstancenoloadbalancer) - _ [EC2::VPC](#EC2::VPC) - _ [Enable DNS](#EnableDNS) - _ [EC2::Subnet](#EC2::Subnet) - _ [EC2::InternetGateway](#EC2::InternetGateway) - _ [EC2::VPCGatewayAttachment](#EC2::VPCGatewayAttachment) - _ [AWS::EC2::RouteTable](#AWS::EC2::RouteTable) - _ [AWS::EC2::Route](#AWS::EC2::Route) - _ [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation) -- [Running notes](#Runningnotes) -- [Reference an input parameter, or a resource ID from inside current template](#ReferenceaninputparameteroraresourceIDfrominsidecurrenttemplate) \* [Using `Fn::Sub`](#UsingFn::Sub) -- [Dynamically referencing resources from another stack.](#Dynamicallyreferencingresourcesfromanotherstack.) +* [Decoupling](#Decoupling) +* [Creating Database + VPC + Subnets in Cloudformation](#CreatingDatabaseVPCSubnetsinCloudformation) +* [Single instance (no load balancer)](#Singleinstancenoloadbalancer) + * [EC2::VPC](#EC2::VPC) + * [Enable DNS](#EnableDNS) + * [EC2::Subnet](#EC2::Subnet) + * [EC2::InternetGateway](#EC2::InternetGateway) + * [EC2::VPCGatewayAttachment](#EC2::VPCGatewayAttachment) + * [AWS::EC2::RouteTable](#AWS::EC2::RouteTable) + * [AWS::EC2::Route](#AWS::EC2::Route) + * [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation) +* [Running notes](#Runningnotes) + * [Database](#Database) +* [Work Commands](#WorkCommands) + * [tags](#tags) + * [deploy](#deploy) + * [delete](#delete) + * [describe-stack-resources](#describe-stack-resources) +* [Adding SSL to ELB](#AddingSSLtoELB) + * [With load balancer](#Withloadbalancer) +* [EB Templates/Resources](#EBTemplatesResources) +* [Configuring security groups](#Configuringsecuritygroups) +* [Elastic Load Balancer](#ElasticLoadBalancer) + * [Elastic Scaler](#ElasticScaler) + * [RDS](#RDS) + * [Security group to allow EC2 instances to talk to each other](#SecuritygrouptoallowEC2instancestotalktoeachother) +* [Custom VPC + Subnets in EB](#CustomVPCSubnetsinEB) +* [Using cloudformation functions in EB config files](#UsingcloudformationfunctionsinEBconfigfiles) +* [Creating a read replica RDS](#CreatingareadreplicaRDS) +* [Multiple security groups on the same resource](#Multiplesecuritygroupsonthesameresource) +* [Private subnets](#Privatesubnets) -* [Decoupling](#Decoupling) -* [Creating Database + VPC + Subnets in Cloudformation](#CreatingDatabaseVPCSubnetsinCloudformation) -* [Single instance (no load balancer)](#Singleinstancenoloadbalancer) - * [EC2::VPC](#EC2::VPC) - * [Enable DNS](#EnableDNS) - * [EC2::Subnet](#EC2::Subnet) - * [EC2::InternetGateway](#EC2::InternetGateway) - * [EC2::VPCGatewayAttachment](#EC2::VPCGatewayAttachment) - * [AWS::EC2::RouteTable](#AWS::EC2::RouteTable) - * [AWS::EC2::Route](#AWS::EC2::Route) - * [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation) -* [Running notes](#Runningnotes) - * [Database](#Database) -* [Work Commands](#WorkCommands) - * [tags](#tags) - * [deploy](#deploy) - * [delete](#delete) - * [describe-stack-resources](#describe-stack-resources) -* [Adding SSL to ELB](#AddingSSLtoELB) - * [With load balancer](#Withloadbalancer) -* [EB Templates/Resources](#EBTemplatesResources) -* [Configuring security groups](#Configuringsecuritygroups) -* [Elastic Load Balancer](#ElasticLoadBalancer) - * [Elastic Scaler](#ElasticScaler) - * [RDS](#RDS) - * [Security group to allow EC2 instances to talk to each other](#SecuritygrouptoallowEC2instancestotalktoeachother) -* [Custom VPC + Subnets in EB](#CustomVPCSubnetsinEB) -* [Using cloudformation functions in EB config files](#UsingcloudformationfunctionsinEBconfigfiles) -* [Creating a read replica RDS](#CreatingareadreplicaRDS) -* [Multiple security groups on the same resource](#Multiplesecuritygroupsonthesameresource) -* [Private subnets](#Privatesubnets) + +- [Decoupling](#Decoupling) +- [Creating Database + VPC + Subnets in Cloudformation](#CreatingDatabaseVPCSubnetsinCloudformation) +- [Single instance (no load balancer)](#Singleinstancenoloadbalancer) + _ [EC2::VPC](#EC2::VPC) + _ [Enable DNS](#EnableDNS) + _ [EC2::Subnet](#EC2::Subnet) + _ [EC2::InternetGateway](#EC2::InternetGateway) + _ [EC2::VPCGatewayAttachment](#EC2::VPCGatewayAttachment) + _ [AWS::EC2::RouteTable](#AWS::EC2::RouteTable) + _ [AWS::EC2::Route](#AWS::EC2::Route) + _ [AWS::EC2::SubnetRouteTableAssociation](#AWS::EC2::SubnetRouteTableAssociation) +- [Running notes](#Runningnotes) \* [Database](#Database) +- [Work Commands](#WorkCommands) + _ [tags](#tags) + _ [deploy](#deploy) + _ [delete](#delete) + _ [describe-stack-resources](#describe-stack-resources) +- [Adding SSL to ELB](#AddingSSLtoELB) \* [With load balancer](#Withloadbalancer) +- [EB Templates/Resources](#EBTemplatesResources) +- [Configuring security groups](#Configuringsecuritygroups) +- [Elastic Load Balancer](#ElasticLoadBalancer) + _ [Elastic Scaler](#ElasticScaler) + _ [RDS](#RDS) \* [Security group to allow EC2 instances to talk to each other](#SecuritygrouptoallowEC2instancestotalktoeachother) +- [Custom VPC + Subnets in EB](#CustomVPCSubnetsinEB) +- [Using cloudformation functions in EB config files](#UsingcloudformationfunctionsinEBconfigfiles) +- [Creating a read replica RDS](#CreatingareadreplicaRDS) +- [Multiple security groups on the same resource](#Multiplesecuritygroupsonthesameresource) +- [Private subnets](#Privatesubnets)