├── .babelrc ├── .cfignore ├── .eslintrc ├── .github ├── pull_request_template.md └── workflows │ └── security-considerations.yml ├── .gitignore ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── SECURITY.md ├── ci ├── README.md ├── build.sh ├── credentials.example.yml └── pipeline.yml ├── gulpfile.babel.js ├── manifest.yml ├── out └── diagrams │ └── pages │ ├── builds.png │ ├── builds.svg │ ├── cicd.png │ ├── cicd.svg │ ├── public_customer_site_requests.png │ ├── public_customer_site_requests.svg │ ├── public_file_storage.png │ ├── public_file_storage.svg │ ├── public_flow.png │ ├── public_flow.svg │ ├── web.png │ └── web.svg ├── package-lock.json ├── package.json ├── scuttle-icon.jpg └── source ├── diagrams ├── .gitignore ├── 10-1-network.mmd ├── 10-4.1-customer-data-flow.mmd ├── 10-4.2-jumpbox.mmd ├── 10-4.3-monitoring.mmd ├── 10-4.4-software-deployment.mmd ├── builds_A.puml ├── builds_B.puml ├── cicd_A.puml ├── cicd_B.puml ├── legend.puml ├── out │ └── public_flow_A │ │ └── public_flow_A.svg ├── pages │ ├── README.md │ ├── builds.mmd │ ├── cicd.mmd │ ├── public_customer_site_requests.mmd │ ├── public_file_storage.mmd │ ├── public_flow.mmd │ └── web.mmd ├── public_flow_A.puml ├── public_flow_B.puml ├── ssp.puml ├── webapp_A.puml └── webapp_B.puml ├── html ├── index.html └── render.html ├── javascript └── start.js └── styles ├── _mermaid.scss ├── _shell.scss └── render.scss /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ] 5 | } 6 | -------------------------------------------------------------------------------- /.cfignore: -------------------------------------------------------------------------------- 1 | .gitignore -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "indent": [ 2, 2 ], 4 | "quotes": [ 2, "single" ], 5 | "linebreak-style": [ 2, "unix" ], 6 | "semi": [ 2, "always" ], 7 | "no-multi-spaces": [ 0 ], 8 | "no-mixed-requires": [ 2, true ], 9 | "strict": [ 0 ] 10 | }, 11 | "env": { 12 | "es6": true, 13 | "node": true, 14 | "browser": true 15 | }, 16 | "parserOptions": { 17 | "sourceType": "module" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Changes proposed in this pull request: 2 | - 3 | - 4 | - 5 | 6 | ## security considerations 7 | [Note the any security considerations here, or make note of why there are none] 8 | -------------------------------------------------------------------------------- /.github/workflows/security-considerations.yml: -------------------------------------------------------------------------------- 1 | name: Security Considerations 2 | 3 | on: 4 | pull_request: 5 | types: [opened, edited, reopened] 6 | branches: [main, master, develop] 7 | 8 | jobs: 9 | security-considerations: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: cloud-gov/security-considerations-action@main 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compass / Sass files 2 | .sass-cache 3 | 4 | # OS and Editor files 5 | .DS_Store 6 | *.DS_Store 7 | Thumbs.db 8 | *.sublime-project 9 | *.sublime-workspace 10 | .svn 11 | .idea 12 | 13 | # Generated public directory 14 | public/ 15 | 16 | # Node modules 17 | node_modules/ 18 | npm-debug.log 19 | 20 | # Dropbox files that get included 21 | .dropbox 22 | /Icon* 23 | 24 | # Adobe Asset Files 25 | *.psd 26 | *.ai 27 | *.indd/vendor/ 28 | 29 | credentials.yml 30 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @cloud-gov/platform-ops @cloud-gov/pages-ops 2 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Welcome! 2 | 3 | We're so glad you're thinking about contributing to an 18F open source project! If you're unsure about anything, just ask -- or submit the issue or pull request anyway. The worst that can happen is you'll be politely asked to change something. We love all friendly contributions. 4 | 5 | We want to ensure a welcoming environment for all of our projects. Our staff follow the [18F Code of Conduct](https://github.com/18F/code-of-conduct/blob/master/code-of-conduct.md) and all contributors should do the same. 6 | 7 | We encourage you to read this project's CONTRIBUTING policy (you are here), its [LICENSE](LICENSE.md), and its [README](README.md). 8 | 9 | If you have any questions or want to read more, check out the [18F Open Source Policy GitHub repository](https://github.com/18f/open-source-policy), or just [shoot us an email](mailto:18f@gsa.gov). 10 | 11 | ## License and attribution 12 | 13 | See [LICENSE](LICENSE.md) for license and attribution details. 14 | 15 | All contributions to this project will be released under the CC0 16 | dedication. By submitting a pull request, you are agreeing to comply 17 | with this waiver of copyright interest. 18 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | ## cg-diagrams is forked from [scuttle](https://github.com/rogeruiz/scuttle), which has the following license: 2 | 3 | 4 | MIT License 5 | 6 | Copyright (c) 2016 Roger Steve Ruiz 7 | 8 | Permission is hereby granted, free of charge, to any person obtaining a copy 9 | of this software and associated documentation files (the "Software"), to deal 10 | in the Software without restriction, including without limitation the rights 11 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | copies of the Software, and to permit persons to whom the Software is 13 | furnished to do so, subject to the following conditions: 14 | 15 | The above copyright notice and this permission notice shall be included in all 16 | copies or substantial portions of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | SOFTWARE. 25 | 26 | ## All modifications by 18F (or other contributors to cg-diagrams) are under the following terms: 27 | 28 | As a work of the United States Government, this project is in the 29 | public domain within the United States. 30 | 31 | Additionally, we waive copyright and related rights in the work 32 | worldwide through the CC0 1.0 Universal public domain dedication. 33 | 34 | ### CC0 1.0 Universal Summary 35 | 36 | This is a human-readable summary of the [Legal Code (read the full text)](https://creativecommons.org/publicdomain/zero/1.0/legalcode). 37 | 38 | #### No Copyright 39 | 40 | The person who associated a work with this deed has dedicated the work to 41 | the public domain by waiving all of his or her rights to the work worldwide 42 | under copyright law, including all related and neighboring rights, to the 43 | extent allowed by law. 44 | 45 | You can copy, modify, distribute and perform the work, even for commercial 46 | purposes, all without asking permission. 47 | 48 | #### Other Information 49 | 50 | In no way are the patent or trademark rights of any person affected by CC0, 51 | nor are the rights that other persons may have in the work or in how the 52 | work is used, such as publicity or privacy rights. 53 | 54 | Unless expressly stated otherwise, the person who associated a work with 55 | this deed makes no warranties about the work, and disclaims liability for 56 | all uses of the work, to the fullest extent permitted by applicable law. 57 | When using or citing the work, you should not imply endorsement by the 58 | author or the affirmer. 59 | 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cloud.gov Diagrams 2 | 3 | Built using [Scuttle](https://github.com/rogeruiz/scuttle). 4 | 5 | ## Installation 6 | 7 | ```shell 8 | npm install 9 | ``` 10 | 11 | ## Development 12 | 13 | ```shell 14 | npm start 15 | ``` 16 | 17 | Then open [http://localhost:1337/](http://localhost:1337/) 18 | 19 | ## Deployment 20 | 21 | For the cloud.gov team, deploy to GovCloud with: 22 | 23 | ```shell 24 | npm run deploy 25 | ``` 26 | 27 | # Pages diagrams 28 | 29 | These are drawn using PlantUML, and are not yet (TODO) rendered at 30 | https://diagrams.fr.cloud.gov. The source code is in ./source/diagrams. 31 | 32 | To manage them, try using VSCode with PlantUML plugin, `jebbs.plantuml`. It should allow you to 33 | then select the option to preview in a side pane as you work. 34 | 35 | The plugin default settings use the public server, 36 | https://www.plantuml.com/plantuml, which may **leak 37 | sensitive information**. Instead, run a local plantuml server: 38 | 39 | ``` 40 | docker run -d -p 8080:8080 plantuml/plantuml-server:tomcat 41 | ``` 42 | 43 | Use Tomcat, as Jetty (as of 2021-02-01) lacks the proper `graphviz` 44 | version. In VSCode, update settings in, `@ext:jebbs.plantuml`, and set 45 | `Plantuml: Server` to `http://localhost:8080` 46 | 47 | The VSCode extension will also generate SVN, PNG, to the `out/` directory. 48 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | 2 | **Reporting Security Issues** 3 | 4 | Please refrain from reporting security vulnerabilities through public GitHub issues. 5 | 6 | Instead, kindly report them via the information provided in [cloud.gov's security.txt](https://cloud.gov/.well-known/security.txt). 7 | 8 | When reporting, include the following details (as much as possible) to help us understand the nature and extent of the potential issue: 9 | 10 | - Type of issue (e.g., buffer overflow, SQL injection, cross-site scripting, etc.) 11 | - Full paths of related source file(s) 12 | - Location of affected source code (tag/branch/commit or direct URL) 13 | - Any special configuration required to reproduce the issue 14 | - Step-by-step instructions to reproduce the issue 15 | - Proof-of-concept or exploit code (if available) 16 | - Impact of the issue, including potential exploitation by attackers 17 | 18 | Providing this information will facilitate a quicker triage of your report. 19 | -------------------------------------------------------------------------------- /ci/README.md: -------------------------------------------------------------------------------- 1 | # Automated deployment 2 | 3 | Uses [Concourse](http://concourse.ci/). To set up deployment, run the following from the top level of the repository: 4 | 5 | ```bash 6 | # configuration 7 | ORG=cloud-gov 8 | SPACE=diagrams 9 | USER=diagrams-deployer 10 | PASS=... 11 | FLY_TARGET=fr 12 | PIPELINE=deploy-diagrams 13 | 14 | # set up the deployment environment 15 | cf create-space $SPACE -o $ORG 16 | cf create-user $USER $PASS 17 | cf set-space-role $USER $ORG $SPACE SpaceDeveloper 18 | 19 | cp ci/credentials.example.yml ci/credentials.yml 20 | 21 | # edit the credentials 22 | vim ci/credentials.yml 23 | 24 | # deploy the pipeline 25 | fly -t $FLY_TARGET set-pipeline -p $PIPELINE -c ci/pipeline.yml -l ci/credentials.yml 26 | fly -t $FLY_TARGET unpause-pipeline -p $PIPELINE 27 | fly -t $FLY_TARGET trigger-job -j $PIPELINE/deploy-production 28 | ``` 29 | -------------------------------------------------------------------------------- /ci/build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | set -x 5 | 6 | npm install 7 | npm run build 8 | 9 | # copy files to output directory, so that they can be read by subsequent step 10 | if [ -n "$COPY_OUTPUT" ]; then 11 | cp -R public/* ../cg-diagrams-compiled 12 | cp manifest.yml ../cg-diagrams-compiled 13 | fi 14 | -------------------------------------------------------------------------------- /ci/credentials.example.yml: -------------------------------------------------------------------------------- 1 | cf-api-url-production: https://api.fr.cloud.gov 2 | cf-deploy-username-production: diagrams-deployer 3 | cf-deploy-password-production: PASSWORD 4 | cf-organization: cloud-gov 5 | cf-space: diagrams 6 | 7 | cg-diagrams-git-url: https://github.com/18F/cg-diagrams.git 8 | cg-diagrams-branch: master 9 | 10 | slack-webhook-url: URL 11 | slack-channel: '#cloud-gov-highbar' 12 | slack-username: concourse 13 | slack-icon-url: http://cl.ly/image/3e1h0H3H2s0P/concourse-logo.png 14 | -------------------------------------------------------------------------------- /ci/pipeline.yml: -------------------------------------------------------------------------------- 1 | --- 2 | jobs: 3 | - name: set-self 4 | plan: 5 | - get: cg-diagrams-source 6 | trigger: true 7 | - set_pipeline: self 8 | file: cg-diagrams-source/ci/pipeline.yml 9 | 10 | - name: deploy-production 11 | plan: 12 | - get: cg-diagrams-source 13 | passed: [set-self] 14 | trigger: true 15 | - task: build 16 | config: 17 | platform: linux 18 | image_resource: 19 | type: registry-image 20 | source: 21 | aws_access_key_id: ((ecr_aws_key)) 22 | aws_secret_access_key: ((ecr_aws_secret)) 23 | repository: general-task 24 | aws_region: us-gov-west-1 25 | tag: latest 26 | inputs: 27 | - name: cg-diagrams-source 28 | outputs: 29 | - name: cg-diagrams-compiled 30 | run: 31 | dir: cg-diagrams-source 32 | path: ci/build.sh 33 | params: 34 | COPY_OUTPUT: 1 35 | - put: cloud-gov-production 36 | params: 37 | platform: linux 38 | image_resource: 39 | type: registry-image 40 | source: 41 | aws_access_key_id: ((ecr_aws_key)) 42 | aws_secret_access_key: ((ecr_aws_secret)) 43 | repository: general-task 44 | aws_region: us-gov-west-1 45 | tag: latest 46 | manifest: cg-diagrams-compiled/manifest.yml 47 | path: cg-diagrams-compiled 48 | current_app_name: diagrams 49 | on_failure: 50 | put: slack 51 | params: 52 | text: | 53 | :x: FAILED to deploy cg-diagrams to Production 54 | <$ATC_EXTERNAL_URL/teams/$BUILD_TEAM_NAME/pipelines/$BUILD_PIPELINE_NAME/jobs/$BUILD_JOB_NAME/builds/$BUILD_NAME|View build details> 55 | channel: ((slack-channel)) 56 | username: ((slack-username)) 57 | icon_url: ((slack-icon-url)) 58 | 59 | resources: 60 | - name: cg-diagrams-source 61 | type: git 62 | source: 63 | uri: https://github.com/cloud-gov/system-diagrams.git 64 | branch: main 65 | commit_verification_keys: ((cloud-gov-pgp-keys)) 66 | 67 | - name: cloud-gov-production 68 | type: cf 69 | source: 70 | api: ((prod-cf-api-url)) 71 | username: ((cf-deploy-username-production)) 72 | password: ((cf-deploy-password-production)) 73 | organization: ((cf-organization)) 74 | space: ((cf-space)) 75 | skip_cert_check: false 76 | 77 | - name: slack 78 | type: slack-notification 79 | source: 80 | url: ((slack-webhook-url)) 81 | 82 | resource_types: 83 | - name: registry-image 84 | type: registry-image 85 | source: 86 | aws_access_key_id: ((ecr_aws_key)) 87 | aws_secret_access_key: ((ecr_aws_secret)) 88 | repository: registry-image-resource 89 | aws_region: us-gov-west-1 90 | tag: latest 91 | 92 | - name: slack-notification 93 | type: registry-image 94 | source: 95 | aws_access_key_id: ((ecr_aws_key)) 96 | aws_secret_access_key: ((ecr_aws_secret)) 97 | repository: slack-notification-resource 98 | aws_region: us-gov-west-1 99 | tag: latest 100 | 101 | - name: git 102 | type: registry-image 103 | source: 104 | aws_access_key_id: ((ecr_aws_key)) 105 | aws_secret_access_key: ((ecr_aws_secret)) 106 | repository: git-resource 107 | aws_region: us-gov-west-1 108 | tag: latest 109 | 110 | - name: cf 111 | type: registry-image 112 | source: 113 | aws_access_key_id: ((ecr_aws_key)) 114 | aws_secret_access_key: ((ecr_aws_secret)) 115 | repository: cf-resource 116 | aws_region: us-gov-west-1 117 | tag: latest 118 | -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | import gulp from 'gulp'; 2 | import colors from 'ansi-colors'; 3 | import log from 'fancy-log'; 4 | import PluginError from 'plugin-error'; 5 | import notifier from 'node-notifier'; 6 | import fs from 'fs'; 7 | import path from 'path'; 8 | import connect from 'connect'; 9 | import serveStatic from 'serve-static'; 10 | import Mustache from 'mustache'; 11 | import through from 'through2'; 12 | import browserify from 'browserify'; 13 | import source from 'vinyl-source-stream'; 14 | import del from 'del'; 15 | import figlet from 'figlet'; 16 | import browserSync from 'browser-sync'; 17 | import gulpSass from 'gulp-sass'; 18 | import coreSass from 'sass'; 19 | 20 | // Create browserSync instance 21 | // 22 | const browserSyncInstance = browserSync.create(); 23 | const sass = gulpSass(coreSass); 24 | 25 | /** 26 | * @name default 27 | * @description The default gulp task. 28 | * @param { function } done - Callback that signals the task is complete. 29 | */ 30 | gulp.task('default', (done) => { 31 | logData(`v${pkg.version}`, pkg.name); 32 | logData('default', pkg.description); 33 | logName('default', done); 34 | }); 35 | 36 | /** 37 | * @name clean 38 | * @desc Deletes the public directory. 39 | * @return { stream } - A stream containing the deleted `public/` directory. 40 | */ 41 | gulp.task('clean', () => del('public')); 42 | 43 | /** 44 | * @name copy:fonts 45 | * @desc Copies `uswds` fonts statically to public. 46 | * @return { stream } - A stream of copied font files. 47 | */ 48 | gulp.task('copy:fonts', () => { 49 | return gulp.src(['node_modules/uswds/dist/fonts/**/*', 'node_modules/font-awesome/fonts/*']) 50 | .pipe(gulp.dest('public/fonts')); 51 | }); 52 | 53 | /** 54 | * @name stylesheets 55 | * @desc Compiles the Sass files under `source/stylesheets`. 56 | * @return { stream } - A stream of compiled CSS files. 57 | */ 58 | gulp.task('stylesheets', gulp.series('copy:fonts', () => { 59 | 60 | return gulp.src('source/styles/render.scss') 61 | .pipe(sass().on('error', sass.logError)) 62 | .pipe(gulp.dest('public')) 63 | .pipe(browserSyncInstance.stream()); 64 | 65 | })); 66 | 67 | /** 68 | * @name javascript 69 | * @desc Bundles and transpiles the JavaScript files under `source/javascript`. 70 | * @return { stream } - A stream of bundled JavaScript files. 71 | */ 72 | gulp.task('javascript', () => { 73 | 74 | const bundler = browserify('source/javascript/start.js') 75 | .transform('babelify', { 76 | global: true, 77 | sourceType: 'module', 78 | presets: ['@babel/preset-env'], 79 | plugins: ['@babel/plugin-transform-modules-commonjs'] 80 | }) 81 | 82 | return bundler.bundle() 83 | .pipe(source('render.js')) 84 | .pipe(gulp.dest('public')); 85 | 86 | }); 87 | 88 | /** 89 | * @name render 90 | * @desc Creates the final HTML page for rendering the mermaid diagrams. 91 | * @see { @link stylesheets } 92 | * @see { @link javascript } 93 | * @return { stream } - A stream of rendered diagrams in HTML files. 94 | */ 95 | gulp.task('render', () => { 96 | 97 | const htmlTemplate = fs.readFileSync('source/html/render.html', 'utf-8'); 98 | 99 | return gulp.src('source/diagrams/**.mmd') 100 | .pipe(renderMermaid(htmlTemplate)) 101 | .pipe(gulp.dest('public')); 102 | 103 | }); 104 | 105 | /** 106 | * @name render:list 107 | * @desc Render a list of all the diagrams available under `source/diagrams`. 108 | * @see { @link render } 109 | * @param { function } done - Callback that signals the task is complete. 110 | */ 111 | gulp.task('render:list', gulp.series('render', (done) => { 112 | 113 | const htmlTemplate = fs.readFileSync('source/html/index.html', 'utf-8'); 114 | 115 | fs.readdir('source/diagrams', (error, files) => { 116 | 117 | let diagrams = files.filter(file => file.includes('.mmd')).map((file) => { 118 | let content = fs.readFileSync('source/diagrams/' + file, 'utf-8'); 119 | let metadata = content.split('\n').filter(function (line) { 120 | return line.match(/^%%/) !== null; 121 | }).reduce(function (memo, line) { 122 | let parts = line.replace(/^%%/, '').split(':').map(function (part) { 123 | return part.trim(); 124 | }); 125 | memo[parts[0]] = parts[1]; 126 | return memo; 127 | }, {}); 128 | 129 | return { 130 | href: `${path.basename(file, '.mmd')}.html`, 131 | name: metadata.title || "needs a title", 132 | description: metadata.description || "need a description" 133 | }; 134 | }); 135 | 136 | var listView = Mustache.render(htmlTemplate, { 137 | 'diagram-list': diagrams, 138 | }); 139 | 140 | fs.writeFile('./public/index.html', listView, (error) => { 141 | if (!error) { 142 | browserSyncInstance.reload(); 143 | done(); 144 | } 145 | }); 146 | 147 | }); 148 | 149 | })); 150 | 151 | /** 152 | * @name server 153 | * @desc Runs a preview server for local development of mermaid diagrams. 154 | * @see { @link render:list } 155 | * @param { function } done - Callback that signals the task is complete. 156 | */ 157 | gulp.task('server', gulp.series('stylesheets', 'javascript', 'render:list', (done) => { 158 | 159 | var port = 1337; 160 | 161 | browserSyncInstance.init({ 162 | proxy: `localhost:${port}`, 163 | }); 164 | 165 | gulp.watch('source/diagrams/*.mmd', gulp.series('render:list')) 166 | .on('change', (event) => { 167 | if ('deleted' === event.type) { 168 | let renderedFileName = `${path.basename(event.path, '.mmd')}.html`; 169 | let destFilePath = path.resolve('public', renderedFileName); 170 | del.sync(destFilePath); 171 | } 172 | browserSyncInstance.reload(); 173 | }); 174 | gulp.watch('source/html/*.html', gulp.series('render:list')); 175 | gulp.watch('source/styles/**/*.scss', gulp.series('stylesheets')); 176 | gulp.watch('source/javascript/**/*.js', gulp.series('javascript')) 177 | .on('change', browserSyncInstance.reload); 178 | 179 | connect() 180 | .use(serveStatic(path.join(__dirname, '/public'), { fallthrough: false })) 181 | .use((error, request, response, next) => { 182 | if (error) { 183 | logError('server', `${error.statusCode} ${error.path}`); 184 | } 185 | next(); 186 | }) 187 | .listen(port, () => { 188 | logName('server'); 189 | logMessage('server', `Site available at http://localhost:${port}/`); 190 | }); 191 | 192 | })); 193 | 194 | /** 195 | * @name build 196 | * @desc Exports the compiled diagrams and pages into the public/ directory. 197 | * @param { function } done - Callback that signals the task is complete. 198 | */ 199 | gulp.task('build', gulp.series('stylesheets', 'javascript', 'render:list', (done) => { 200 | logMessage('build', 'Build complete.'); 201 | done(); 202 | })); 203 | 204 | /** 205 | * @name notify 206 | * @desc Wrapper around node-notify. 207 | * @see { @link logError } 208 | * @see { @link logMessage } 209 | * @param { string } title - The title of the notification. 210 | * @param { string } message - The message fo the notification. 211 | */ 212 | const notify = (title, message) => { 213 | notifier.notify({ 214 | title: title, 215 | message: message, 216 | icon: 'scuttle-icon.jpg', 217 | }); 218 | }; 219 | 220 | /** 221 | * @name logData 222 | * @desc Wrapper for gulp-util for logging task data. 223 | * @param { string } task - The name of the task. 224 | * @param { string } data - The data for the task. 225 | */ 226 | const logData = (task, data) => { 227 | log( 228 | colors.cyan(task), 229 | colors.white(data) 230 | ); 231 | }; 232 | 233 | /** 234 | * @name logMessage 235 | * @desc Wrapper for gulp-util for logging task messages. 236 | * @param { string } task - The name of the task. 237 | * @param { string } message - The message for the task. 238 | */ 239 | const logMessage = (task, message) => { 240 | notify(task, message); 241 | log( 242 | colors.cyan(task), 243 | colors.yellow(message) 244 | ); 245 | }; 246 | 247 | /** 248 | * @name logError 249 | * @desc Wrapper for gulp-util for logging task errors. 250 | * @param { string } task - The name of the task. 251 | * @param { string } message - The error message for the task. 252 | */ 253 | const logError = (task, message) => { 254 | log( 255 | colors.red(task), 256 | colors.yellow(message) 257 | ); 258 | }; 259 | 260 | /** 261 | * @name logName 262 | * @desc Display the name of the project. 263 | * @param { string } task - The name of the task. 264 | * @param { function } done - A callback to run. 265 | */ 266 | const logName = (task, done) => { 267 | figlet(pkg.name, { 268 | font: `Isometric${Math.floor(Math.random() * (4 - 1 + 1)) + 1}`, 269 | }, (error, data) => { 270 | if (!error) { 271 | data.split('\n') 272 | .forEach((line) => { 273 | logData(task, line); 274 | }); 275 | logData(task, ''); 276 | } 277 | if ('function' === typeof done) { 278 | done(); 279 | } 280 | }); 281 | }; 282 | 283 | /** 284 | * @name renderMermaid 285 | * @desc Gulp plugin for rendering Mermaid diagrams within a Mustache template. 286 | * @param { string } template - The Mustache template. 287 | * @return { stream } - A node stream wrapped in through2. 288 | */ 289 | const renderMermaid = function (template) { 290 | 291 | const taskName = 'render-mermaid'; 292 | 293 | if (!template) { 294 | throw new PluginError(taskName, 'Missing a Mustache template.'); 295 | } 296 | 297 | template = new Buffer.from(template); 298 | 299 | return through.obj(function (file, encoding, callback) { 300 | 301 | if (file.isNull()) { 302 | return callback(null, file); 303 | } 304 | 305 | let fileName = path.basename(file.path, '.mmd'); 306 | logMessage(taskName, `Processing ${file.path}`); 307 | 308 | if (file.isBuffer()) { 309 | file.contents = new Buffer.from(Mustache.render(template.toString(), { 310 | 'diagram-title': fileName, 311 | 'diagram-contents': file.contents.toString(), 312 | })); 313 | 314 | file.path = path.join(path.dirname(file.path), `${fileName}.html`); 315 | } 316 | if (file.isStream()) { 317 | this.emit('error', new PluginError(taskName, 'Streaming not supported')); 318 | return callback(null, file); 319 | } 320 | 321 | callback(null, file); 322 | }); 323 | }; 324 | -------------------------------------------------------------------------------- /manifest.yml: -------------------------------------------------------------------------------- 1 | applications: 2 | - name: diagrams 3 | instances: 2 4 | memory: 256M 5 | disk_quota: 1024M 6 | routes: 7 | - route: diagrams.fr.cloud.gov 8 | buildpacks: 9 | - staticfile_buildpack 10 | path: public 11 | -------------------------------------------------------------------------------- /out/diagrams/pages/builds.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-gov/system-diagrams/7b2e298fa78d6041fd29d1d655447c25979d4bd7/out/diagrams/pages/builds.png -------------------------------------------------------------------------------- /out/diagrams/pages/builds.svg: -------------------------------------------------------------------------------- 1 |
AWS Gov Cloud
GSA Authorized SaaS Connection
cloud.gov platform
Pages cloud.gov production space
cloud.gov space services
Commits update to source code
HTTPS Port 443
Webhook request to start build
HTTPS Port 443
Proxy request
HTTPS Port 443
Creates site build record
TLS Port 5432
Starts site build event job
TLS Port 6379
Sends site build job data via the site builds queue
TLS Port 6379
Sends site build task request
HTTPS Port 443
Starts site build task
HTTPS Port 443
Publishes site files
HTTPS Port 443
Sends build status
HTTPS Port 443
Sends build logs
TLS Port 5432
Legend
👤 User
Process
Database
Load Balancer / Router
Pages Web Application
*Node.js
Pages Build Container
Builds and publishes site
*Docker
Pages Worker
Runs background job manage site builds
*Node.js
Control Plane
*CloudFoundry Task
Database
*AWS RDS Postgres
Key/Value Store
*AWS Elasticache Redis
Object Store
*AWS S3
Customer Site Source Control
*GitHub
👤
UnPrivileged User
*A Pages customer
-------------------------------------------------------------------------------- /out/diagrams/pages/cicd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-gov/system-diagrams/7b2e298fa78d6041fd29d1d655447c25979d4bd7/out/diagrams/pages/cicd.png -------------------------------------------------------------------------------- /out/diagrams/pages/public_customer_site_requests.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-gov/system-diagrams/7b2e298fa78d6041fd29d1d655447c25979d4bd7/out/diagrams/pages/public_customer_site_requests.png -------------------------------------------------------------------------------- /out/diagrams/pages/public_file_storage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-gov/system-diagrams/7b2e298fa78d6041fd29d1d655447c25979d4bd7/out/diagrams/pages/public_file_storage.png -------------------------------------------------------------------------------- /out/diagrams/pages/public_file_storage.svg: -------------------------------------------------------------------------------- 1 |

AWS Gov Cloud

AWS Commercial Cloud

cloud.gov platform

Pages cloud.gov production space

cloud.gov space services

dedicated customer site bucket

cloud.gov platform

All Users
HTTPS Port 443

Manages Public File Storage
HTTPS Port 443

Request
HTTPS Port 443

Read/Write File Management
Authenticated TLS Port 5432

Read/Write File Storage
Authenticated HTTPS

Views Public File
HTTPS/443

Views Public File
HTTPS/443

Yes

No

Proxy Request
HTTPS/443

Proxy Site Requests
HTTPS/443

Legend

👤 User

Process

Database

👤
Unprivileged User
*Pages Customer

👤
Public User
*A member of the public

CDN
AWS CloudFront

Pages Proxy Application
*NGINX

Load Balancer / Router

Authentication Provider
*UAA

Pages Web Application
*Node.js

Web Application Firewall

Is request cached

Database
*AWS RDS Postgres

File Store
*AWS S3

-------------------------------------------------------------------------------- /out/diagrams/pages/public_flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-gov/system-diagrams/7b2e298fa78d6041fd29d1d655447c25979d4bd7/out/diagrams/pages/public_flow.png -------------------------------------------------------------------------------- /out/diagrams/pages/public_flow.svg: -------------------------------------------------------------------------------- 1 |
AWS Gov Cloud
AWS Commercial Cloud
cloud.gov platform
Pages cloud.gov production space
cloud.gov space services
cloud.gov platform
Views Static Content
HTTPS/443
Views Static Content
HTTPS/443
Yes
No
Proxy Request
HTTPS/443
Proxy Request
HTTPS/443
Proxy Site Requests
HTTPS/443
Legend
👤 User
Process
Database
Decision
Load Balancer / Router
AWS Application Load Balancer
Pages Proxy Application
*NGINX
Object Store
*AWS S3
Web Application Firewall
Is request cached
CDN
AWS CloudFront
👤
Public User
*A member of the public
-------------------------------------------------------------------------------- /out/diagrams/pages/web.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-gov/system-diagrams/7b2e298fa78d6041fd29d1d655447c25979d4bd7/out/diagrams/pages/web.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cg-diagrams", 3 | "description": "Mermaid-based flow charts and diagrams using the US Draft Web Design Standards", 4 | "private": true, 5 | "main": "gulpfile.js", 6 | "type": "module", 7 | "engines": { 8 | "node": ">=18" 9 | }, 10 | "scripts": { 11 | "build": "gulp build", 12 | "deploy": "npm run build && npm run target && npm run push", 13 | "prestart": "gulp clean", 14 | "push": "cf push", 15 | "start": "gulp server", 16 | "target": "cf target -o cloud-gov -s diagrams", 17 | "test": "echo \"Error: no test specified\" && exit 1" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git+https://github.com/rogeruiz/scuttle.git" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "^7.11.6", 25 | "@babel/plugin-transform-modules-commonjs": "^7.10.4", 26 | "@babel/preset-env": "^7.11.5", 27 | "@babel/register": "^7.11.5", 28 | "ansi-colors": "^4.1.1", 29 | "babelify": "^10.0.0", 30 | "browser-sync": "^3.0.3", 31 | "browserify": "^17.0.1", 32 | "connect": "^3.4.1", 33 | "sass": "^1.86.3", 34 | "del": "^8.0.0", 35 | "fancy-log": "^1.3.3", 36 | "figlet": "^1.1.2", 37 | "font-awesome": "^4.6.3", 38 | "gulp": "^5.0.0", 39 | "gulp-sass": "^5.1.0", 40 | "mermaid": "^11.6.0", 41 | "mustache": "^2.2.1", 42 | "node-notifier": "^8.0.1", 43 | "plugin-error": "^1.0.1", 44 | "save-svg-as-png": "git+https://github.com/exupero/saveSvgAsPng#f56023b", 45 | "serve-static": "^1.16.1", 46 | "through2": "^2.0.1", 47 | "uswds": "^2.8.1", 48 | "vinyl-source-stream": "^2.0.0" 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /scuttle-icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cloud-gov/system-diagrams/7b2e298fa78d6041fd29d1d655447c25979d4bd7/scuttle-icon.jpg -------------------------------------------------------------------------------- /source/diagrams/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | -------------------------------------------------------------------------------- /source/diagrams/10-1-network.mmd: -------------------------------------------------------------------------------- 1 | %% title: 10-1 Network 2 | %% description: Section 10 - System Environment - Figure 10-1 Network 3 | graph LR 4 | subgraph External Services 5 | github["GitHub"] 6 | slack["Slack"] 7 | statuspage["StatusPage"] 8 | googlegroups["Google Groups"] 9 | end 10 | subgraph AWS US East/West 11 | cloudfront["AWS CloudFront"] 12 | route53["AWS Route53"] 13 | end 14 | subgraph AWS GovCloud 15 | apps-alb["Customer ALB"] 16 | ops-alb["UAA & Concourse ALB"] 17 | s3["AWS S3"] 18 | cloudwatch["AWS CloudWatch"] 19 | cloudwatch-logs["AWS CloudWatch Logs"] 20 | config["AWS Config"] 21 | cloudtrail["AWS CloudTrail"] 22 | iam["AWS IAM"] 23 | iam-perms["AWS IAM Permissions"] 24 | iam-roles["AWS IAM Roles"] 25 | aws-console["AWS Console"] 26 | subgraph Staging VPC 27 | vpc-staging{Copy of Production VPC} 28 | end 29 | subgraph Development VPC 30 | vpc-development{Copy of Production VPC} 31 | end 32 | subgraph cloud.gov Authorization Boundary 33 | subgraph Production VPC 34 | subgraph Availability Zones us-gov-west-1a/b 35 | subgraph Public Subnet 36 | prod-nat["NAT Gateway"] 37 | prod-alb-endpoint("ALB Endpoint") 38 | end 39 | subgraph Private Subnet - Core Tier A 40 | prod-cf{"Cloud Foundry
Core Components"} 41 | idp["cloud.gov fallback IDP"] 42 | end 43 | subgraph Private Subnet - Core Tier B 44 | prod-diego{"Cloud Foundry
Container Management"} 45 | end 46 | subgraph Private Subnet - Database Tier 47 | prod-rds{"AWS RDS instances"} 48 | end 49 | subgraph Private Subnet - Services Tier 50 | prod-services{"Service instances"} 51 | end 52 | end 53 | vpc-router-prod["VPC Router"] 54 | end 55 | vpc-peering["VPC Peering Connection"] 56 | subgraph Tooling VPC 57 | subgraph Tooling Availability Zones us-gov-west-1a/b 58 | subgraph Public Subnet 59 | tooling-nat["NAT Gateway"] 60 | tooling-alb-endpoint("ALB Endpoint") 61 | end 62 | subgraph Private Subnet - Operations Tier 63 | tooling-ops["BOSH Director/UAA"] 64 | end 65 | subgraph Private Subnet - Database Tier 66 | tooling-rds{"AWS RDS instances"} 67 | end 68 | subgraph Private Subnet - Concourse Tier 69 | tooling-concourse["Concourse - production"] 70 | end 71 | end 72 | vpc-router-tooling["VPC Router"] 73 | end 74 | end 75 | end 76 | customer(("Customer")) 77 | ops(("Cloud Operations")) 78 | 79 | customer-.DNS UDP 53.->route53 80 | customer--Web HTTP 80 or HTTPS 443-->cloudfront 81 | customer--Web HTTP 80 or HTTPS 443-->apps-alb 82 | customer--Web HTTPS 443-->statuspage 83 | 84 | cloudfront--Web HTTPS 443-->apps-alb 85 | prod-services-.create service instance TLS 443.->cloudfront 86 | prod-services-.create service instance TLS 443.->s3 87 | 88 | ops--Web HTTPS 443-->ops-alb 89 | ops--Web HTTPS 443-->github 90 | ops--Web HTTPS 443-->slack 91 | ops--Web HTTPS 443-->aws-console 92 | ops--Web HTTPS 443-->statuspage 93 | ops--Web HTTPS 443-->googlegroups 94 | 95 | tooling-nat--Alerting TLS 587-->googlegroups 96 | 97 | vpc-router-tooling-->vpc-peering 98 | vpc-router-prod-->vpc-peering 99 | vpc-staging-->vpc-peering 100 | vpc-development-->vpc-peering 101 | aws-console-."Authentication/Authorization".->iam 102 | iam-.->iam-perms 103 | iam-perms-.->iam-roles 104 | 105 | apps-alb---prod-alb-endpoint 106 | prod-alb-endpoint---prod-nat 107 | prod-nat---prod-cf 108 | prod-nat---prod-diego 109 | prod-nat---prod-rds 110 | prod-nat---prod-services 111 | 112 | ops-alb---tooling-alb-endpoint 113 | tooling-alb-endpoint---tooling-nat 114 | tooling-nat---tooling-ops 115 | tooling-nat---tooling-rds 116 | tooling-nat---tooling-concourse 117 | 118 | -------------------------------------------------------------------------------- /source/diagrams/10-4.1-customer-data-flow.mmd: -------------------------------------------------------------------------------- 1 | %% title: 10-4.1 Customer Data Flow 2 | %% description: Section 10 - System Environment - Figure 10-4.1 Customer Data Flow 3 | graph LR 4 | subgraph AWS GovCloud 5 | subgraph Cloud Foundry Components 6 | subgraph Container Management Segments 7 | Cell["Cell"] 8 | AppContainer{"Customer
Application"} 9 | Dashboard{Dashboard
dashboard.fr.cloud.gov} 10 | end 11 | Router{Router} 12 | SSHProxy[SSH Proxy] 13 | UAA["User Authentication/Authorization (UAA)
login.fr.cloud.gov"] 14 | CloudController[Cloud Controller
api.fr.cloud.gov] 15 | ServiceBroker[Service Broker] 16 | InternalService["Internal Service
e.g. Service Account
Identity Provider"] 17 | HM[Health Monitor] 18 | Loggregator[Loggregator] 19 | end 20 | subgraph Customer Logs 21 | Q[AWS Elasticache Redis Queue] 22 | Logstash[Logstash] 23 | OS[Opensearch] 24 | OSD[Opensearch Dashboard
logs.fr.cloud.gov] 25 | end 26 | subgraph AWS Brokered Services VPC 27 | AWSService("AWS Services e.g.
AWS RDS Postgresql, MySQL
AWS Elasticache Redis
AWS OpenSearch") 28 | end 29 | subgraph SAML IDP 30 | SAML{cloud.gov fallback IDP
providing MFA} 31 | end 32 | ALB("Application Load Balancer (ALB)") 33 | CloudControllerDB(Cloud Controller
RDS DB) 34 | CloudWatch[AWS CloudWatch Logs] 35 | S3[S3] 36 | end 37 | subgraph Customer Responsibility 38 | CustomerSAML{"Single Sign-on (SSO)
providing MFA"} 39 | end 40 | subgraph AWS East/West 41 | cloudfront["AWS CloudFront"] 42 | end 43 | 44 | Customer((Customer)) 45 | statuspage["StatusPage
cloudgov.statuspage.io"] 46 | 47 | 48 | Router-->Cell 49 | SSHProxy--SSH using temporary key-->Router 50 | CloudController-.API Request Sets up temporary SSH key.->SSHProxy 51 | CloudController--Request for provision-->ServiceBroker 52 | CloudController--Provision/scale application instances-->Cell 53 | CloudControllerDB-->CloudController 54 | ServiceBroker--Provisions-->InternalService 55 | ServiceBroker--Provisions-->AWSService 56 | InternalService--Service protocol-->AppContainer 57 | AWSService--Service protocol-->AppContainer 58 | HM--Monitoring of assigned port-->AppContainer 59 | Cell-.Container.->AppContainer 60 | AppContainer-->Loggregator 61 | Cell-.Container.->Dashboard 62 | 63 | Loggregator-->Logstash 64 | Logstash-->Q 65 | Q-->OS 66 | Logstash-->CloudWatch 67 | Logstash-->S3 68 | OS-->OSD 69 | 70 | Customer--"Web HTTP 80 or HTTPS 443"-->ALB 71 | Customer--SSH port 2222 using temporary key-->ALB 72 | Customer--"Web request HTTPS 443"-->statuspage 73 | Customer--"Web HTTP 80 or HTTPS 443"-->cloudfront 74 | 75 | cloudfront --"Web request HTTPS 443"--> ALB 76 | 77 | ALB --SSH port 2222 using temporary key--> SSHProxy 78 | ALB --"Web HTTP 80 or HTTPS 443"--> Router 79 | ALB --API request HTTPS 443--> CloudController 80 | ALB -- "Triggered by web request HTTPS 443 only" --> OSD 81 | 82 | UAA-.Authentication.->CustomerSAML 83 | UAA-.Authentication.->SAML 84 | CloudController-.Authorization.->UAA 85 | SSHProxy-.Authorization.->UAA 86 | OSD-.Authorization.->UAA 87 | -------------------------------------------------------------------------------- /source/diagrams/10-4.2-jumpbox.mmd: -------------------------------------------------------------------------------- 1 | %% title: 10-4.2 Jumpbox Data Flow 2 | %% description: Section 10 - System Environment - Figure 10-4.2 Jumpbox Data Flow 3 | graph TD 4 | 5 | subgraph AWS GovCloud 6 | UAA["User Authentication/Authorization (UAA)"] 7 | concourse["Concourse Server"] 8 | worker[Concourse Worker] 9 | Jumpbox{Ephemeral Jumpbox} 10 | BOSH[BOSH Director] 11 | EC2[AWS EC2 Instances] 12 | ALB("AWS Application Load Balancer (ALB)") 13 | opsuaaweb["UAA Web UI
(presents CLI authentication token)"] 14 | end 15 | subgraph GSA Responsibility 16 | SAML{"Single Sign-on (SSO)
providing MFA
GSA Auth (Okta)"} 17 | end 18 | subgraph GSA VPN and Internet Egress 19 | ZScalerDNS("ZScaler DNS") 20 | GSAProxy("GSA Internet Proxy") 21 | end 22 | 23 | Ops((Cloud Operations)) 24 | 25 | Ops--"Concourse Web UI HTTPS 443"-->ZScalerVPN-->ZScalerDNS-->GSAProxy-->ALB 26 | Ops=="Concourse CLI (fly) HTTPS 443"==>ZScalerVPN==>ZScalerDNS==>GSAProxy==>ALB 27 | ALB--Run Jumpbox pipeline-->concourse 28 | ALB==Access via fly CLI
with token==>concourse 29 | concourse==CLI routed to Jumpbox SSH 2222==>Jumpbox 30 | ALB--Request token for CLI-->opsuaaweb-->UAA 31 | UAA-.Authentication.->SAML 32 | concourse-.Authorization.->UAA 33 | concourse-.Run jumpbox job.->worker 34 | worker-.Launch Container.->Jumpbox 35 | Jumpbox--BOSH SSH request-->BOSH 36 | BOSH-.BOSH Director sets up temporary SSH key.->EC2 37 | Jumpbox==Access EC2 via SSH 22 using temporary key==>EC2 38 | -------------------------------------------------------------------------------- /source/diagrams/10-4.3-monitoring.mmd: -------------------------------------------------------------------------------- 1 | %% title: 10-4.3 Monitoring & Alerting Data Flow 2 | %% description: Section 10 - System Environment - Figure 10-4.3 Monitoring & Alerting Data Flow 3 | graph LR 4 | subgraph AWS GovCloud 5 | alb["AWS Application Load Balancer
(ALB)"] 6 | UAA["User Authentication/Authorization (UAA)"] 7 | aws-logs["AWS CloudWatch Logs"] 8 | aws-cloudwatch["AWS CloudWatch"] 9 | aws-console["AWS Console"] 10 | aws-iam("AWS IAM") 11 | aws-guardduty["AWS GuardDuty"] 12 | aws-cloudwatch-alarms["AWS Cloudwatch Alarms"] 13 | subgraph Cloud Foundry Components 14 | boshdirector{"BOSH Director"} 15 | firehose{"Metrics"} 16 | concourse{"Concourse
(CI/CD Pipelines)"} 17 | end 18 | subgraph Centralized Monitoring Components 19 | nessus{"Nessus Manager"} 20 | prometheus{"Prometheus
Alerting/Storage"} 21 | grafana{"Grafana
(Time Series Visualizations)"} 22 | doomsday{"Doomsday
(Certificate Monitoring)"} 23 | end 24 | subgraph All EC2 Instances 25 | nessusagent["Nessus
Scanning
Agent"] 26 | clamav["ClamAV
(Virus/Malware)"] 27 | logs["System Logs"] 28 | aws-logs-agent["AWS
CloudWatch
Logs Agent"] 29 | snort["Snort IDS
(Intrusion Detection)"] 30 | boshagent["BOSH Agent"] 31 | node-exporter["Prometheus Node Exporter"] 32 | aide["AIDE
(Filesystem Integrity)"] 33 | end 34 | end 35 | subgraph GSA Responsibility 36 | SAML{"Single Sign-on (SSO)
providing MFA"} 37 | end 38 | subgraph External 39 | statuspage["StatusPage"] 40 | sp-account["StatusPage Account"] 41 | clamav-updates>"ClamAV Updates"] 42 | Googlegroups["Google Groups"] 43 | snort-updates>"Snort Network
Vulnerability Profiles"] 44 | tenable-updates>"Tenable Updates"] 45 | slack["GSA Slack"] 46 | end 47 | email("Email") 48 | Ops((Cloud Operations)) 49 | zscaler("Zscaler VPN") 50 | 51 | nessusagent--Sends Scanning Results-->nessus 52 | nessus--Monitors-->nessusagent 53 | nessus--Reports SMTP 587-->email 54 | tenable-updates--Security Definition Updates-->nessus 55 | 56 | node-exporter--System Performance Metrics-->prometheus 57 | firehose-->prometheus 58 | boshagent-->boshdirector 59 | boshdirector--Health Monitor state changes-->prometheus 60 | 61 | logs--Sends Logs-->aws-logs-agent 62 | logs--Sends Performance Metrics-->aws-cloudwatch 63 | aws-logs-agent--Sends Log Data-->aws-logs 64 | aws-console--View Logs-->aws-logs 65 | 66 | clamav-updates--Security Definition Updates-->clamav 67 | clamav--Sends Alerts-->prometheus 68 | aide--Sends Alerts-->prometheus 69 | logs--Sends Logs-->prometheus 70 | 71 | snort-updates--Security Definition Updates-->snort 72 | snort--Sends Alerts-->prometheus 73 | 74 | prometheus--Visualizes events-->grafana 75 | alb-->grafana 76 | alb-->doomsday 77 | prometheus--Processes alerts SMTP 587-->Googlegroups 78 | Googlegroups-->email 79 | 80 | UAA-.Authentication.->SAML 81 | grafana-.Authorization.->UAA 82 | doomsday-.Authorization.->UAA 83 | 84 | aws-console-."Authentication/Authorization".->aws-iam 85 | statuspage-."Authentication/Authorization".->sp-account 86 | email-->Ops 87 | Ops--HTTPS 443-->zscaler 88 | zscaler--HTTPS 443-->alb 89 | Ops--HTTPS 443-->aws-console 90 | Ops--HTTPS 443-->Googlegroups 91 | 92 | aws-guardduty--Findings SMTP 587-->Googlegroups 93 | aws-cloudwatch-alarms--Alarm Notifications SMTP 587-->Googlegroups 94 | aws-cloudwatch-alarms--AWS Login Failure Alerts HTTPS 443-->slack 95 | concourse--Pipeline Status HTTPS 443-->slack 96 | doomsday--Expiration Warnings HTTPS 443-->slack -------------------------------------------------------------------------------- /source/diagrams/10-4.4-software-deployment.mmd: -------------------------------------------------------------------------------- 1 | %% title: 10-4.4 Software Deployment Data Flow 2 | %% description: Section 10 - System Environment - Figure 10-4.3 Software Deployment Data Flow 3 | graph TD 4 | subgraph AWS GovCloud 5 | subgraph Concourse 6 | web["Concourse Web Server"] 7 | worker["Concourse Worker"] 8 | test-job("Test Build") 9 | deploy-job("Deployment Build") 10 | end 11 | alb["AWS Application Load Balancer (ALB)"] 12 | UAA["User Authentication/Authorization (UAA)"] 13 | bosh{"BOSH Director"} 14 | ec2{"AWS EC2 Instance"} 15 | end 16 | subgraph External 17 | github["GitHub Repository"] 18 | github-auth{"GitHub Account
MFA Authentication"} 19 | end 20 | subgraph GSA Responsibility 21 | SAML{"Single Sign-on (SSO)
providing MFA"} 22 | end 23 | Ops((Cloud Operations)) 24 | Zscaler["ZscalerVPN"] 25 | 26 | Ops--"SSH 22 or HTTPS 443
(software changes)"-->github 27 | Ops--Web HTTP 80 or HTTPS 443-->Zscaler-->alb 28 | alb--Run Pipeline-->web 29 | web--Pipeline job-->worker 30 | web-.Authorization.->UAA 31 | UAA-.Authentication.->SAML 32 | github-."Authentication/Authorization".->github-auth 33 | worker-.Runs automated tests against the software.->test-job 34 | worker-."Only starts when Test Build passes".->deploy-job 35 | test-job--Downloads latest version-->github 36 | deploy-job--Downloads same version that passed Test Build-->github 37 | deploy-job--Instructs BOSH to deploy-->bosh 38 | bosh--Deploys changes-->ec2 -------------------------------------------------------------------------------- /source/diagrams/builds_A.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include ssp.puml 3 | 4 | hide stereotype 5 | 6 | skinparam rectangle<> { 7 | backgroundColor #FFFFFF 8 | borderColor Transparent 9 | titleFontColor Red 10 | stereotypeFontColor Transparent 11 | shadowing false 12 | fontColor grey 13 | } 14 | 15 | skinparam note { 16 | BorderColor Green 17 | } 18 | 19 | Person(npu, "Nonprivileged User", "A Pages Customer") 20 | 21 | note "Auth: OAuth 2.0 \n via Github MFA" as githubpagesauth 22 | note "Auth: Token" as webhook 23 | 24 | 25 | Boundary(gsa, "GSA Authorized SaaS") { 26 | System_Ext(gh, "Github", "Customer Source Control") 27 | } 28 | 29 | Boundary(awsgov, "AWS GovCloud") { 30 | Boundary(cloudgov, "cloud.gov") { 31 | 'This hidden rectangle keeps Auth near to each other while behing in d 32 | 'different boundaries 33 | ' rectangle gfaconnect<> [ 34 | ' | 35 | ' ] 36 | ' rectangle webhookconnect<> [ 37 | ' / 38 | ' ] 39 | System_Inherited(elb, "Load Balancer / Router", "cloud.gov") 40 | System_Inherited(cc, "Control Plane", "cloud.gov") 41 | System(core, "Pages Web", "//[Node JS]//") 42 | System(builder, "Pages Builder", "//[Node JS]//") 43 | System(build, "Pages Build Container", "//[Docker Image]//") 44 | Db_Shared(db, "Postgres", "AWS RDS") 45 | Db_Shared(redis, "Redis", "cloud.gov Redis") 46 | Db_Shared(s3, "Object Storage", "AWS S3") 47 | } 48 | System_Inherited(queue, "Build Queue", "AWS SQS") 49 | } 50 | s3-[hidden]redis 51 | ' Main flow 52 | HTTPS(npu, gh, "1. commits code modification") 53 | note on link 54 | Auth: MFA 55 | end note 56 | 57 | HTTPS(gh, elb, "2. sends webhook notification") 58 | note on link 59 | Auth: Token 60 | end note 61 | 62 | HTTP_Variable(elb, core, "3. proxies request") 63 | 64 | HTTPS(core, queue, "4. sends build message") 65 | note on link 66 | Auth: Credentials 67 | end note 68 | 69 | HTTPS(builder, queue, "5. requests build message") 70 | note on link 71 | Auth: Credentials 72 | end note 73 | 74 | HTTPS(builder, cc, "6. requests build") 75 | note on link 76 | Auth: Credentials 77 | end note 78 | 79 | cc -> build : **7. restages build container** 80 | 81 | HTTPS(build, gh, "8. checks out code") 82 | note on link 83 | Auth: Credentials 84 | (if private) 85 | end note 86 | 87 | HTTPS(build, s3, "9. sends build results") 88 | note on link 89 | Auth: Credentials 90 | end note 91 | 92 | ' Other flows 93 | TCPS_Variable(core, db, "reads/writes build metadata & configuration") 94 | note on link 95 | Auth: Credentials/Network 96 | end note 97 | 98 | TCPS_Variable(core, redis, "reads/writes build notifications") 99 | note on link 100 | Auth: Credentials 101 | end note 102 | 103 | ' Authentication annotations 104 | npu . githubpagesauth 105 | githubpagesauth . core 106 | 107 | gh .. webhook 108 | webhook .. core 109 | @enduml 110 | -------------------------------------------------------------------------------- /source/diagrams/builds_B.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include ssp.puml 3 | 4 | hide stereotype 5 | 6 | skinparam rectangle<> { 7 | backgroundColor #FFFFFF 8 | borderColor Transparent 9 | titleFontColor Red 10 | stereotypeFontColor Transparent 11 | shadowing false 12 | fontColor grey 13 | } 14 | 15 | skinparam note { 16 | BorderColor Green 17 | } 18 | 19 | Person(npu, "Nonprivileged User", "A cloud.gov Pages Customer") 20 | note "Auth: Token" as webhook 21 | 22 | Boundary(gsa, "Agency-authorized VCS") { 23 | System_Ext(gh, "e.g., Github", "Customer Source Control") 24 | } 25 | 26 | Boundary(awsgov, "AWS GovCloud") { 27 | Boundary(cloudgov, "cloud.gov") { 28 | Boundary(cloudgovplat, "cloud.gov Platform") { 29 | 'This hidden rectangle keeps Auth near to each other while behing in d 30 | 'different boundaries 31 | ' rectangle webhookconnect<> [ 32 | ' / 33 | ' ] 34 | System_Inherited(elb, "Load Balancer / Router", "cloud.gov") 35 | note "Auth: OAuth 2.0 \n via cloud.gov Platform MFA" as githubpagesauth 36 | System_Inherited(cc, "Control Plane", "cloud.gov") 37 | System(core, "Pages Web", "//[Node JS]//") 38 | System(builder, "Pages Builder", "//[Node JS]//") 39 | System(build, "Pages Build Container", "//[Docker Image]//") 40 | Db_Shared(db, "Postgres", "AWS RDS") 41 | Db_Shared(redis, "Redis", "cloud.gov Redis") 42 | Db_Shared(s3, "Object Storage", "AWS S3") 43 | } 44 | System_Inherited(queue, "Build Queue", "AWS SQS") 45 | } 46 | } 47 | 'make hidden connections to keep build queue, 48 | 'newly brought into boundary, less associated 49 | 'with other elements so it stays on the edge 50 | 'This probably could have been cleaner with an invisible 51 | 'boundary for DynamoDB and Queue 52 | 'core -[hidden]cc 53 | 'core -[hidden]db 54 | 's3 -[hidden]redis 55 | 'redis -[hidden]db 56 | 57 | 58 | HTTPS(npu, gh, "1. commits code modification") 59 | note on link 60 | Auth: MFA 61 | end note 62 | 63 | HTTPS(gh, elb, "2. sends webhook notification") 64 | note on link 65 | Auth: Token 66 | end note 67 | 68 | HTTP(elb, core, "3. proxies request") 69 | 70 | HTTPS(core, queue, "4. sends build message") 71 | note on link 72 | Auth: Credentials 73 | end note 74 | 75 | HTTPS(builder, queue, "5. requests build message") 76 | note on link 77 | Auth: Credentials 78 | end note 79 | 80 | HTTPS(builder, cc, "6. requests build") 81 | note on link 82 | Auth: Credentials 83 | end note 84 | 85 | cc -> build : **7. restages build container** 86 | 87 | HTTPS(build, gh, "8. checks out code") 88 | note on link 89 | Auth: Credentials 90 | (if private) 91 | end note 92 | 93 | HTTPS(build, s3, "9. sends build results") 94 | note on link 95 | Auth: Credentials 96 | end note 97 | 98 | ' Other flows 99 | TCPS_Variable(core, db, "reads/writes build metadata & configuration") 100 | note on link 101 | Auth: Credentials/Network 102 | end note 103 | 104 | TCPS_Variable(core, redis, "reads/writes build notifications") 105 | note on link 106 | Auth: Credentials 107 | end note 108 | 109 | ' Authentication annotations 110 | npu .. githubpagesauth 111 | githubpagesauth .. core 112 | gh . webhook 113 | webhook ... core 114 | @enduml 115 | -------------------------------------------------------------------------------- /source/diagrams/cicd_A.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include ssp.puml 3 | 4 | hide stereotype 5 | 6 | Person(pu, "Privileged User", "A Pages Developer") 7 | 8 | Boundary(gsa, "GSA-\nAuthorized\nSaaS") { 9 | System_Ext(gh, "Github", "Source Control") 10 | System_Ext(circle, "Circle", "CI") 11 | System_Ext(cc, "Code Climate", "Static Analysis") 12 | } 13 | 14 | Boundary(awsgov, "AWS GovCloud") { 15 | Boundary(cloudgov, "cloud.gov Platform") { 16 | System_Inherited(cg, "Control Plane", "cloud.gov") 17 | System(core, "Pages Application", "//[Node JS/Nginx]//") 18 | } 19 | Db_Shared(ecr, "Container Registry", "AWS ECR") 20 | } 21 | 22 | ' Main flow 23 | HTTPS(pu, gh, "1. merges Pull Request") 24 | note on link 25 | Auth: MFA 26 | end note 27 | 28 | HTTPS_Tight(gh, circle, "2. sends webhook notification") 29 | note on link 30 | Auth: Token 31 | end note 32 | 33 | HTTPS_Tight(circle, cc, "sends analysis results") 34 | note on link 35 | Auth: Token 36 | end note 37 | 38 | HTTPS(circle, cg, "3a. sends source") 39 | note on link 40 | Auth: Credentials 41 | end note 42 | 43 | HTTPS(circle, ecr, "3b. sends image") 44 | note on link 45 | Auth: Credentials 46 | end note 47 | 48 | cg -> core : **4a. builds and deploys application** 49 | 50 | HTTPS(cg, ecr, "4b. fetches image") 51 | note on link 52 | Auth: Credentials 53 | end note 54 | 55 | @enduml 56 | -------------------------------------------------------------------------------- /source/diagrams/cicd_B.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include ssp.puml 3 | 4 | hide stereotype 5 | 6 | Person(pu, "Privileged User", "A Pages Developer") 7 | 8 | Boundary(gsa, "GSA-Authorized SaaS") { 9 | System_Ext(gh, "Github", "Source Control") 10 | } 11 | 12 | Boundary(awsgov, "AWS GovCloud") { 13 | Boundary(cloudgov_boundary, "cloud.gov"){ 14 | System(sq, "SonarQube", "Static Analysis") 15 | System(circle, "Concourse", "CI") 16 | Boundary(cloudgov, "cloud.gov Platform") { 17 | System_Inherited(cg, "Control Plane", "cloud.gov") 18 | System(core, "Pages Application", "//[Node JS/Nginx]//") 19 | } 20 | Db_Shared(ecr, "Container Registry", "AWS ECR") 21 | } 22 | } 23 | 24 | ' Main flow 25 | HTTPS(pu, gh, "1. merges Pull Request") 26 | note on link 27 | Auth: MFA 28 | end note 29 | 30 | HTTPS(gh, circle, "2. sends webhook notification") 31 | note on link 32 | Auth: Token 33 | end note 34 | 35 | HTTPS_Tight(circle, sq, "sends analysis results") 36 | note on link 37 | Auth: Token 38 | end note 39 | 40 | HTTPS(circle, cg, "3a. sends source") 41 | note on link 42 | Auth: Credentials 43 | end note 44 | 45 | HTTPS(circle, ecr, "3b. sends image") 46 | note on link 47 | Auth: Credentials 48 | end note 49 | 50 | cg -> core : **4a. builds and deploys application** 51 | 52 | HTTPS(cg, ecr, "4b. fetches image") 53 | note on link 54 | Auth: Credentials 55 | end note 56 | @enduml 57 | -------------------------------------------------------------------------------- /source/diagrams/legend.puml: -------------------------------------------------------------------------------- 1 | !include ssp.puml 2 | 3 | hide stereotype 4 | legend right 5 | | **Legend** | 6 | |:------------------------------------------------------------------------- | 7 | | <$EXTERNAL_PERSON_BG_COLOR> external person | 8 | | <$INHERITED_BG_COLOR> inherited system | 9 | | <$SHARED_BG_COLOR> shared system | 10 | | <$SYSTEM_BG_COLOR> Pages system | 11 | | <$EXTERNAL_SYSTEM_BG_COLOR> external system | 12 | | encrypted connection | 13 | | unencrypted connection | 14 | endlegend 15 | -------------------------------------------------------------------------------- /source/diagrams/out/public_flow_A/public_flow_A.svg: -------------------------------------------------------------------------------- 1 | AWS GovCloudcloud.gov PlatformAWS Commercialcloud.gov PlatformLoad Balancer /Router[cloud.gov]Federalist Proxy[Nginx]Object Store[AWS S3]CDN[AWS Cloudfront]Public ViewerA member of the public1a. views staticcontent[https 443 (T)]Custom Domains1b. views staticcontent[https 443 (T)]Preview Domains2. proxies requests[https 443 (T)]3. proxies requests[http * (T)]4. proxies requests[https 443 (T)]Legend:-----------------external personinherited systemshared systemFederalist systemencrypted connection|unencrypted connection| -------------------------------------------------------------------------------- /source/diagrams/pages/README.md: -------------------------------------------------------------------------------- 1 | cg-diagrams Pages 2 | ================= 3 | 4 | Information about the cloud.gov Pages diagrams and how to create them. These diagrams are related to the system's different data and workflows using [mermaid diagrams](https://mermaid.js.org/). 5 | 6 | ## How to 7 | 8 | The diagrams are written in mermaid and the diagram images are generated using the [mermaid cli](https://github.com/mermaid-js/mermaid-cli) 9 | 10 | ### Generating diagram images 11 | 12 | #### Install the CLI 13 | 14 | `npm install -g @mermaid-js/mermaid-cli` 15 | 16 | #### Generate an image from a diagram 17 | 18 | `mmdc -i source/diagrams/pages/diagram-a.mmd -o out/diagrams/pages/diagram-a.png --width 5000` 19 | 20 | Options: 21 | - `-i`: Input mermaid diagram 22 | - `-o`: Output PNG image 23 | - `--width`: Width of the out put *Note: Diagram width in output is 25000* 24 | 25 | #### Storing the diagram images 26 | 27 | All generated images should be stored in [out/diagrams/pages](../../../out/diagrams/pages/) and should be named the same as the corresponding mermaid diagram. 28 | -------------------------------------------------------------------------------- /source/diagrams/pages/builds.mmd: -------------------------------------------------------------------------------- 1 | flowchart TB 2 | %% Styles 3 | classDef userStyle stroke:#167CC5,stroke-width:4px 4 | classDef processStyle stroke:#bc0061,stroke-width:4px 5 | classDef processSuccessStyle stroke:#bc0061,stroke-width:4px 6 | classDef decisionStyle stroke:#ea8d02,stroke-width:4px 7 | classDef saasStyle stroke:#f2ff07,stroke-width:4px 8 | classDef dbStyle stroke:#010daf,stroke-width:4px 9 | 10 | %% Component Defintions 11 | 12 | %% Users 13 | user["👤
UnPrivileged User
*A Pages customer"]:::userStyle 14 | 15 | %% Processors 16 | aws_load_balancer[Load Balancer / Router]:::processStyle 17 | pages_app[Pages Web Application
*Node.js]:::processStyle 18 | pages_worker[Pages Worker
Runs background job manage site builds
*Node.js]:::processStyle 19 | pages_build_container[Pages Build Container
Builds and publishes site
*Docker]:::processStyle 20 | control_plane[Control Plane
*CloudFoundry Task]:::processStyle 21 | 22 | %% SaaS 23 | gh_source[Customer Site Source Control
*GitHub]:::saasStyle 24 | 25 | %% Store 26 | database[(Database
*AWS RDS Postgres)]:::dbStyle 27 | key_value_store[(Key/Value Store
*AWS Elasticache Redis)]:::dbStyle 28 | s3[(Object Store
*AWS S3)]:::dbStyle 29 | 30 | %% Flow 31 | user -- Commits update to source code
HTTPS Port 443 --> gh_source 32 | gh_source -- Webhook request to start build
HTTPS Port 443 --> aws_load_balancer 33 | aws_load_balancer -- Proxy request
HTTPS Port 443 --> pages_app 34 | pages_app -- Creates site build record
TLS Port 5432 --> database 35 | pages_app -- Starts site build event job
TLS Port 6379 --> key_value_store 36 | key_value_store -- Sends site build job data via the site builds queue
TLS Port 6379 --> pages_worker 37 | pages_worker -- Sends site build task request
HTTPS Port 443 --> control_plane 38 | control_plane -- Starts site build task
HTTPS Port 443 --> pages_build_container 39 | pages_build_container -- Publishes site files
HTTPS Port 443 --> s3 40 | pages_build_container -- Sends build status
HTTPS Port 443 --> pages_app 41 | pages_build_container -- Sends build logs
TLS Port 5432 --> database 42 | 43 | %% Layout 44 | subgraph GSA Authorized SaaS Connection 45 | gh_source 46 | end 47 | 48 | subgraph AWS Gov Cloud 49 | aws_load_balancer 50 | subgraph cloud.gov platform 51 | subgraph Pages cloud.gov production space 52 | pages_app 53 | pages_build_container 54 | pages_worker 55 | control_plane 56 | subgraph cloud.gov space services 57 | database 58 | key_value_store 59 | s3 60 | end 61 | end 62 | end 63 | end 64 | 65 | subgraph Legend 66 | direction BT 67 | legend_user["👤 User"]:::userStyle 68 | legend_process[Process]:::processStyle 69 | legend_db[(Database)]:::dbStyle 70 | end 71 | -------------------------------------------------------------------------------- /source/diagrams/pages/cicd.mmd: -------------------------------------------------------------------------------- 1 | flowchart TB 2 | %% Styles 3 | classDef userStyle stroke:#167CC5,stroke-width:4px 4 | classDef processStyle stroke:#bc0061,stroke-width:4px 5 | classDef processSuccessStyle stroke:#bc0061,stroke-width:4px 6 | classDef decisionStyle stroke:#ea8d02,stroke-width:4px 7 | classDef saasStyle stroke:#f2ff07,stroke-width:4px 8 | classDef dbStyle stroke:#010daf,stroke-width:4px 9 | 10 | %% Component Defintions 11 | 12 | %% Users 13 | user["👤
Privileged User
*A Pages Operator"]:::userStyle 14 | 15 | %% Processors 16 | ci_test[Test Source Code
*CI Task]:::processStyle 17 | ci_deploy[Deploy Pages App
*CI Tasks]:::processStyle 18 | ci_notify_success["✅
Notify Success Status
*CI Tasks"]:::processSuccessStyle 19 | ci_notify_failure["❌
Notify Failure Status
*CI Tasks"]:::processStyle 20 | pages_app[Pages Web Application
*Node.js]:::processStyle 21 | 22 | %% Decisions 23 | did_tests_pass{Are tests passing?}:::decisionStyle 24 | did_deploy{Did Pages app deploy?}:::decisionStyle 25 | 26 | %% SaaS 27 | gh_source[Source Control
*GitHub]:::saasStyle 28 | 29 | %% Store 30 | container_registry[(Container Registry Store
*AWS ECR)]:::processStyle 31 | 32 | %% Flow 33 | user -- Merges Pull Request
HTTPS/443 --> gh_source 34 | ci_test <-- Polls Source Code For Update
SSH/22 --> gh_source 35 | ci_test <-- Pulls Test Container Image --> container_registry 36 | ci_test -- Runs Tests --> did_tests_pass 37 | did_tests_pass -- No --> ci_notify_failure 38 | did_tests_pass -- Yes --> ci_deploy 39 | ci_deploy <-- Pulls Deploy Container Image --> container_registry 40 | ci_deploy --> did_deploy 41 | did_deploy -- No --> ci_notify_failure 42 | did_deploy -- Yes --> pages_app 43 | did_deploy -- Yes --> ci_notify_success 44 | ci_notify_success --> gh_source 45 | ci_notify_failure --> gh_source 46 | 47 | %% Layout 48 | subgraph GSA Authorized SaaS Connection 49 | gh_source 50 | end 51 | 52 | subgraph AWS Gov Cloud 53 | subgraph cloud.gov tooling 54 | subgraph CI: Concourse CI 55 | ci_test 56 | did_tests_pass 57 | ci_deploy 58 | ci_notify_success 59 | ci_notify_failure 60 | did_deploy 61 | end 62 | container_registry 63 | end 64 | subgraph cloud.gov platform 65 | subgraph Pages cloud.gov production space 66 | pages_app 67 | end 68 | end 69 | end 70 | 71 | subgraph Legend 72 | direction BT 73 | legend_user["👤 User"]:::userStyle 74 | legend_process[Process]:::processStyle 75 | legend_db[(Database)]:::dbStyle 76 | legend_decision{Decision}:::decisionStyle 77 | end 78 | -------------------------------------------------------------------------------- /source/diagrams/pages/public_customer_site_requests.mmd: -------------------------------------------------------------------------------- 1 | flowchart TB 2 | %% Styles 3 | classDef userStyle stroke:#167CC5,stroke-width:4px 4 | classDef processStyle stroke:#bc0061,stroke-width:4px 5 | classDef externalStyle fill:#e4eee9,stroke:#000,stroke-width:4px,stroke-dasharray: 4 5 6 | classDef decisionStyle stroke:#ea8d02,stroke-width:4px 7 | classDef dbStyle stroke:#010daf,stroke-width:4px 8 | classDef authStyle stroke:#000000,stroke-width:4px 9 | 10 | %% Style Subgrapohs 11 | classDef customerGraphStyle fill:#FFF1EB 12 | classDef cgGraphStyle fill:#E3EEFF 13 | classDef blank fill:#fff; 14 | 15 | %% Component Defintions 16 | 17 | %% Users 18 | admin["👤
Site Admin
Manages Web Site"]:::userStyle 19 | user["👤
Public User
Navigates to site URL"]:::userStyle 20 | 21 | %% Processors 22 | aws_cdn[CDN
AWS CloudFront]:::processStyle 23 | aws_load_balancer[Load Balancer / Router
AWS Application Load Balancer]:::processStyle 24 | pages_proxy[Pages Proxy Application
*NGINX]:::processStyle 25 | pages_builder[Site Builder
Generates Site Files]:::processStyle 26 | waf[Web Application Firewall]:::processStyle 27 | 28 | %% Databases 29 | s3[(Published Website
File Storage
*AWS S3)]:::dbStyle 30 | 31 | %% Customers Components 32 | dns_config[DNS Records]:::dbStyle 33 | github[(Github Repository
Site Source)]:::dbStyle 34 | auth(("🔐
Authenticated
Request")):::authStyle 35 | public_auth(("🌎
Web Browser
Public
Unauthenticated
Request")):::authStyle 36 | webhook[Automated Webhook
Starts Build]:::processStyle 37 | 38 | %% External Services 39 | search[Search.gov]:::externalStyle 40 | dap[Digital Analytics Program
DAP]:::externalStyle 41 | touchpoints[Touchpoints]:::externalStyle 42 | 43 | %% Public Flow 44 | public_auth -. Site Web Request
HTTPS/443 .-> dap 45 | public_auth -. Site Web Request
HTTPS/443 .-> search 46 | public_auth -. Site Web Request
HTTPS/443 .-> touchpoints 47 | user -- Site Web Request
HTTPS/443 --> public_auth --> waf --> aws_cdn 48 | waf -- Site Web Response
HTTPS/443 --> public_auth -- Site Web Response
HTTPS/443 --> user 49 | aws_cdn --> waf 50 | aws_cdn -- Site Web Request
HTTPS/443 --> aws_load_balancer 51 | aws_load_balancer -- Site Web Response
HTTPS/443 --> aws_cdn 52 | aws_load_balancer -- Site Web Request
HTTPS/443 --> pages_proxy 53 | pages_proxy -- Site Web Response
HTTPS/443 --> aws_load_balancer 54 | 55 | pages_proxy -- Site Web Request
HTTPS/443 --> s3 56 | s3 -- Site Web Response
HTTPS/443 --> pages_proxy 57 | 58 | %% Customer Flow 59 | 60 | admin --> auth --> github 61 | github --> webhook -- HTTP POST Request
HTTPS/443 --> pages_builder 62 | dns_config -- Site Domain DNS Records --> aws_cdn 63 | pages_builder -- Publishes Site
HTTPS/443
File Upload --> s3 64 | 65 | %% Layout 66 | subgraph Customer 67 | subgraph DNS 68 | dns_config 69 | end 70 | subgraph Github 71 | github 72 | webhook 73 | end 74 | end 75 | 76 | subgraph Pages[cloud.gov Pages] 77 | subgraph aws_gov_cloud[AWS Gov Cloud] 78 | subgraph cg_platform[cloud.gov platform] 79 | aws_load_balancer 80 | subgraph cg_pages_space[Pages cloud.gov production space] 81 | pages_proxy 82 | pages_builder 83 | subgraph cg_pages_services[cloud.gov space services] 84 | s3 85 | end 86 | end 87 | end 88 | end 89 | 90 | subgraph aws_com[AWS Commercial cloud] 91 | subgraph cg_platform_2[cloud.gov platform] 92 | waf 93 | aws_cdn 94 | end 95 | end 96 | end 97 | 98 | subgraph Legend 99 | direction BT 100 | legend_user["👤 User"]:::userStyle 101 | legend_process[Process]:::processStyle 102 | legend_external[Optional External Service]:::externalStyle 103 | legend_db[(Database)]:::dbStyle 104 | legend_config[Configuration]:::dbStyle 105 | legend_connect((Authentication
Type)):::authStyle 106 | end 107 | 108 | subgraph external[Optional External Services] 109 | dap 110 | search 111 | touchpoints 112 | end 113 | 114 | class Customer customerGraphStyle 115 | class DNS customerGraphStyle 116 | class Github customerGraphStyle 117 | class Legend blank 118 | class external externalStyle 119 | 120 | class Pages cgGraphStyle 121 | class aws_com cgGraphStyle 122 | class aws_gov_cloud cgGraphStyle 123 | class cg_platform cgGraphStyle 124 | class cg_platform_2 cgGraphStyle 125 | class cg_pages_space cgGraphStyle 126 | class cg_pages_services cgGraphStyle 127 | -------------------------------------------------------------------------------- /source/diagrams/pages/public_file_storage.mmd: -------------------------------------------------------------------------------- 1 | flowchart TB 2 | direction BT 3 | 4 | %% Styles 5 | classDef userStyle stroke:#167CC5,stroke-width:4px 6 | classDef processStyle stroke:#bc0061,stroke-width:4px 7 | classDef dbStyle stroke:#010daf,stroke-width:4px 8 | 9 | 10 | %% Users 11 | user_unprivleged["👤
Unprivileged User
*Pages Customer"]:::userStyle 12 | user["👤
Public User
*A member of the public"]:::userStyle 13 | 14 | 15 | %% Processors 16 | aws_cdn[CDN
AWS CloudFront]:::processStyle 17 | pages_proxy[Pages Proxy Application
*NGINX]:::processStyle 18 | aws_load_balancer[Load Balancer / Router]:::processStyle 19 | auth_provider[Authentication Provider
*UAA]:::processStyle 20 | pages_app[Pages Web Application
*Node.js]:::processStyle 21 | 22 | 23 | %% Services 24 | waf[Web Application Firewall]:::processStyle 25 | 26 | 27 | %% Decisions 28 | is_cached{Is request cached}:::decisionStyle 29 | 30 | 31 | %% Databases 32 | database[(Database
*AWS RDS Postgres)]:::dbStyle 33 | s3[(File Store
*AWS S3)]:::dbStyle 34 | 35 | 36 | %% Flow 37 | %%%% Pages Customer 38 | auth_provider -- All Users
HTTPS Port 443--> pages_app 39 | user_unprivleged -- Manages Public File Storage
HTTPS Port 443 --> aws_load_balancer 40 | aws_load_balancer -- Request
HTTPS Port 443 --> auth_provider 41 | pages_app -- Read/Write File Management
Authenticated TLS Port 5432 --> database 42 | pages_app -- Read/Write File Storage
Authenticated HTTPS --> s3 43 | 44 | %%%%%%%% Styling 45 | linkStyle 0,1,2,3,4 stroke-width:4px,fill:none,stroke:navy 46 | 47 | %%%% Public 48 | user -- Views Public File
HTTPS/443 --> waf 49 | waf -- Views Public File
HTTPS/443 --> is_cached 50 | is_cached -- Yes --> aws_cdn 51 | is_cached -- No --> aws_load_balancer 52 | aws_load_balancer -- Proxy Request
HTTPS/443 --> pages_proxy 53 | pages_proxy -- Proxy Site Requests
HTTPS/443 --> s3 54 | 55 | %%%%%%%% Styling 56 | linkStyle 5,6,7,8,9,10 stroke-width:4px,fill:none,stroke:orange 57 | 58 | 59 | %% Layout 60 | subgraph AWS Commercial Cloud 61 | waf 62 | is_cached 63 | subgraph cloud.gov platform 64 | aws_cdn 65 | end 66 | end 67 | 68 | subgraph AWS Gov Cloud 69 | aws_load_balancer 70 | subgraph cloud.gov platform 71 | auth_provider 72 | subgraph Pages cloud.gov production space 73 | pages_app 74 | pages_proxy 75 | subgraph cloud.gov space services 76 | database 77 | subgraph dedicated customer site bucket 78 | s3 79 | end 80 | end 81 | end 82 | end 83 | end 84 | 85 | subgraph Legend 86 | direction BT 87 | legend_user["👤 User"]:::userStyle 88 | legend_process[Process]:::processStyle 89 | legend_db[(Database)]:::dbStyle 90 | end 91 | -------------------------------------------------------------------------------- /source/diagrams/pages/public_flow.mmd: -------------------------------------------------------------------------------- 1 | flowchart TB 2 | %% Styles 3 | classDef userStyle stroke:#167CC5,stroke-width:4px 4 | classDef processStyle stroke:#bc0061,stroke-width:4px 5 | classDef decisionStyle stroke:#ea8d02,stroke-width:4px 6 | classDef dbStyle stroke:#010daf,stroke-width:4px 7 | 8 | %% Component Defintions 9 | 10 | %% Users 11 | user["👤
Public User
*A member of the public"]:::userStyle 12 | 13 | %% Processors 14 | aws_cdn[CDN
AWS CloudFront]:::processStyle 15 | aws_load_balancer[Load Balancer / Router
AWS Application Load Balancer]:::processStyle 16 | pages_proxy[Pages Proxy Application
*NGINX]:::processStyle 17 | 18 | %% Services 19 | waf[Web Application Firewall]:::processStyle 20 | 21 | %% Decisions 22 | is_cached{Is request cached}:::decisionStyle 23 | 24 | %% Databases 25 | s3[(Object Store
*AWS S3)]:::dbStyle 26 | 27 | %% Flow 28 | user -- Views Static Content
HTTPS/443 --> waf 29 | waf -- Views Static Content
HTTPS/443 --> is_cached 30 | is_cached -- Yes --> aws_cdn 31 | is_cached -- No --> aws_load_balancer 32 | aws_cdn -- Proxy Request
HTTPS/443 --> aws_load_balancer 33 | aws_load_balancer -- Proxy Request
HTTPS/443 --> pages_proxy 34 | 35 | pages_proxy -- Proxy Site Requests
HTTPS/443 --> s3 36 | 37 | %% Layout 38 | subgraph AWS Commercial Cloud 39 | waf 40 | is_cached 41 | subgraph cloud.gov platform 42 | aws_cdn 43 | end 44 | end 45 | 46 | subgraph AWS Gov Cloud 47 | subgraph cloud.gov platform 48 | aws_load_balancer 49 | subgraph Pages cloud.gov production space 50 | pages_proxy 51 | subgraph cloud.gov space services 52 | s3 53 | end 54 | end 55 | end 56 | end 57 | 58 | subgraph Legend 59 | direction BT 60 | legend_user["👤 User"]:::userStyle 61 | legend_process[Process]:::processStyle 62 | legend_db[(Database)]:::dbStyle 63 | legend_decision{Decision}:::decisionStyle 64 | end 65 | -------------------------------------------------------------------------------- /source/diagrams/pages/web.mmd: -------------------------------------------------------------------------------- 1 | flowchart TB 2 | direction BT 3 | %% Styles 4 | classDef userStyle stroke:#167CC5,stroke-width:4px 5 | classDef processStyle stroke:#bc0061,stroke-width:4px 6 | classDef saasStyle stroke:#f2ff07,stroke-width:4px 7 | classDef dbStyle stroke:#010daf,stroke-width:4px 8 | 9 | %% Component Defintions 10 | 11 | %% Users 12 | user_privleged["👤
Privileged User
*Pages Operator"]:::userStyle 13 | user_unprivleged["👤
Unprivileged User
*Pages Cusomter"]:::userStyle 14 | 15 | %% SaaS 16 | gh_auth_provider[Authorization Provider
*GitHub]:::saasStyle 17 | dap[Analytics
*DAP]:::saasStyle 18 | 19 | %% Processors 20 | aws_load_balancer[Load Balancer / Router]:::processStyle 21 | auth_provider[Authentication Provider
*UAA]:::processStyle 22 | pages_app[Pages Web Application
*Node.js]:::processStyle 23 | pages_admin[Pages Admin Application
*Static]:::processStyle 24 | pages_mailer[Pages Mailer
*Node.js]:::processStyle 25 | smtp_server[SMTP Server
*Postfix]:::processStyle 26 | 27 | %% Databases 28 | database[(Database
*AWS RDS Postgres)]:::dbStyle 29 | key_value_store[(Key/Value Store
*AWS Elasticache Redis)]:::dbStyle 30 | 31 | %% Flow 32 | user_privleged -- Request Content
HTTPS Port 443 --> aws_load_balancer 33 | auth_provider -- Privleged Users
HTTP Port 443--> pages_admin 34 | auth_provider -- All Users
HTTPS Port 443--> pages_app 35 | 36 | user_unprivleged -- Request Content
HTTPS Port 443 --> aws_load_balancer 37 | aws_load_balancer -- Request
HTTPS Port 443 --> auth_provider 38 | user_unprivleged -- Authorizes Oauth
HTTPS Port 443 --> gh_auth_provider 39 | gh_auth_provider -- Stores Oauth Token
HTTPS Port 443 --> pages_app 40 | user_unprivleged -- Reports Usage
HTTPS Port 443 --> dap 41 | 42 | 43 | pages_app -- Read/Write Site Management
Authenticated TLS Port 5432 --> database 44 | pages_app -- Read/Write Site Notifications
Authenticated TLS Port 6379 --> key_value_store 45 | pages_app -- Request Send Email
Authenticated HTTPS Port 443 --> pages_mailer 46 | 47 | pages_admin -- Read/Write Site Management
Authenticated HTTPS Port 443 --> pages_app 48 | pages_mailer -- Sends Email
SMTP --> smtp_server 49 | 50 | %% Layout 51 | subgraph GSA Authorized SaaS Connection 52 | gh_auth_provider 53 | end 54 | 55 | subgraph GSA Authorized SaaS Monitoring 56 | dap 57 | end 58 | 59 | subgraph AWS Gov Cloud 60 | aws_load_balancer 61 | subgraph cloud.gov platform 62 | auth_provider 63 | subgraph Pages cloud.gov production space 64 | pages_app 65 | pages_admin 66 | pages_mailer 67 | smtp_server 68 | subgraph cloud.gov space services 69 | database 70 | key_value_store 71 | end 72 | end 73 | end 74 | end 75 | 76 | subgraph Legend 77 | direction BT 78 | legend_user["👤 User"]:::userStyle 79 | legend_process[Process]:::processStyle 80 | legend_db[(Database)]:::dbStyle 81 | legend_saas[Software as a service
*SaaS]:::saasStyle 82 | end 83 | -------------------------------------------------------------------------------- /source/diagrams/public_flow_A.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include ssp.puml 3 | 4 | hide stereotype 5 | 6 | Person_Ext(public, "Public Viewer", "A member of the public") 7 | 8 | Boundary(awsgov, "AWS GovCloud") { 9 | Boundary(cloudgov_gc, "cloud.gov Platform") { 10 | System_Inherited(elb, "Load Balancer / Router", "cloud.gov") 11 | System(proxy, "Pages Proxy", "//[Nginx]//") 12 | Db_Shared(s3, "Object Store", "AWS S3") 13 | } 14 | } 15 | Boundary(awscom, "AWS Commercial") { 16 | Boundary(cloudgov_ew, "cloud.gov Platform") { 17 | System_Shared(cdn, "CDN", "AWS Cloudfront") 18 | } 19 | } 20 | 21 | HTTPS(public, cdn, "1a. views static content") 22 | note on link 23 | Custom Domains 24 | end note 25 | 26 | HTTPS(public, elb, "1b. views static content") 27 | note on link 28 | Preview Domains 29 | end note 30 | 31 | 32 | cdn -[#green,thickness=2]>> elb : **2. proxies requests**\n//[https 443 (T)]// 33 | HTTP_Variable(elb, proxy, "3. proxies requests") 34 | HTTPS(proxy, s3, "4. proxies requests") 35 | @enduml 36 | -------------------------------------------------------------------------------- /source/diagrams/public_flow_B.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include https://raw.githubusercontent.com/cloud-gov/cg-diagrams/puml/source/diagrams/ssp.puml 3 | 4 | hide stereotype 5 | legend right 6 | | **Legend** | 7 | |:------------------------------------------------------------------------- | 8 | | <$EXTERNAL_PERSON_BG_COLOR> external person | 9 | | <$INHERITED_BG_COLOR> inherited system | 10 | | <$SHARED_BG_COLOR> shared system | 11 | | <$SYSTEM_BG_COLOR> Pages system | 12 | | encrypted connection | 13 | | unencrypted connection | 14 | endlegend 15 | 16 | Person_Ext(public, "Public Viewer", "A member of the public") 17 | 18 | Boundary(awsgov, "AWS GovCloud") { 19 | Boundary(cloudgov_gc, "cloud.gov Platform") { 20 | Db_Shared(s3, "Object Store", "AWS S3") 21 | } 22 | } 23 | Boundary(awscom, "AWS Commercial") { 24 | Boundary(cloud_gov_core, "cloud.gov") { 25 | Boundary(cloudgov_ew, "cloud.gov Platform") { 26 | System_Shared(cdn, "CDN", "AWS Cloudfront") 27 | } 28 | System_Shared(lambda, "CDN", "AWS Cloudfront/Lambda@Edge") 29 | } 30 | } 31 | 32 | HTTPS(public, cdn, "1a. views static content") 33 | note on link 34 | Custom Domains 35 | end note 36 | 37 | HTTPS(public, lambda, "1b. views static content") 38 | note on link 39 | Preview Domains 40 | end note 41 | 42 | 43 | cdn -[#green,thickness=2]>> lambda : **2. proxies requests**\n//[https 443 (T)]// 44 | HTTPS(lambda, s3, "3a. proxies requests") 45 | 46 | @enduml -------------------------------------------------------------------------------- /source/diagrams/ssp.puml: -------------------------------------------------------------------------------- 1 | ' C4-PlantUML-SSP 2 | ' https://github.com/davemcorwin/c4-plantuml-ssp/ 3 | ' Inspired by and borrowed heavily from https://github.com/adrianvlupu/C4-PlantUML 4 | 5 | !include https://raw.githubusercontent.com/adrianvlupu/C4-PlantUML/latest/C4_Component.puml 6 | 7 | !global $TLS_COLOR = "#green" 8 | !global $ATO_COLOR = "FireBrick" 9 | !global $UNENCRYPTED_CONNECTION_COLOR = "#666666" 10 | !global $INHERITED_BG_COLOR = $COMPONENT_BG_COLOR 11 | !global $SHARED_BG_COLOR = $CONTAINER_BG_COLOR 12 | 13 | skinparam arrow { 14 | FontColor #black 15 | } 16 | 17 | skinparam rectangle<> { 18 | BorderColor $ATO_COLOR 19 | BorderStyle dashed 20 | BorderThickness 2 21 | FontColor $ATO_COLOR 22 | } 23 | 24 | !unquoted procedure HTTPS($from, $to, $label) 25 | $from --[$TLS_COLOR,thickness=2]>> $to : **$label**\n//[https 443 (T)]// 26 | !endprocedure 27 | 28 | 'Use 1 dash, -, instead of 2, to components closer 29 | !unquoted procedure HTTPS_Tight($from, $to, $label) 30 | $from -[$TLS_COLOR,thickness=2]>> $to : **$label**\n//[https 443 (T)]// 31 | !endprocedure 32 | 33 | !unquoted procedure HTTP($from, $to, $label) 34 | $from -->> $to : **$label**\n//[http 80 (T)]// 35 | !endprocedure 36 | 37 | !unquoted procedure HTTP_Variable($from, $to, $label) 38 | $from -->> $to : **$label**\n//[http * (T)]// 39 | !endprocedure 40 | 41 | !unquoted procedure HTTPS_Variable($from, $to, $label) 42 | $from --[$TLS_COLOR,thickness=2]>> $to : **$label**\n//[https * (T)]// 43 | !endprocedure 44 | 45 | !unquoted procedure TCP($from, $to, $label) 46 | $from -->> $to : **$label**\n//[tcp 80 (T)]// 47 | !endprocedure 48 | 49 | !unquoted procedure TCPS($from, $to, $label, $forward=%true()) 50 | !if ($forward == %true()) 51 | $from --[$TLS_COLOR,thickness=2]>> $to : **$label**\n//[tcp 443 (T)]// 52 | !else 53 | $from <<--[$TLS_COLOR,thickness=2] $to : **$label**\n//[tcp 443 (T)]// 54 | !endif 55 | !endprocedure 56 | 57 | !unquoted procedure TCP_Variable($from, $to, $label) 58 | $from -->> $to : **$label**\n//[tcp * (T)]// 59 | !endprocedure 60 | 61 | !unquoted procedure TCPS_Variable($from, $to, $label) 62 | $from --[$TLS_COLOR,thickness=2]>> $to : **$label**\n//[tcp * (T)]// 63 | !endprocedure 64 | 65 | !unquoted function ATO_Boundary($alias, $label) 66 | !return 'rectangle "=='+$label+'" <> as '+$alias 67 | !endfunction 68 | 69 | !unquoted procedure System_Inherited($alias, $label, $techn) 70 | Component($alias, $label, $techn) 71 | !endprocedure 72 | 73 | !unquoted procedure Db_Inherited($alias, $label, $techn) 74 | ComponentDb($alias, $label, $techn) 75 | !endprocedure 76 | 77 | !unquoted procedure System_Shared($alias, $label, $techn) 78 | Container($alias, $label, $techn) 79 | !endprocedure 80 | 81 | !unquoted procedure Db_Shared($alias, $label, $techn) 82 | ContainerDb($alias, $label, $techn) 83 | !endprocedure 84 | -------------------------------------------------------------------------------- /source/diagrams/webapp_A.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include https://raw.githubusercontent.com/cloud-gov/cg-diagrams/puml/source/diagrams/ssp.puml 3 | 4 | hide stereotype 5 | legend right 6 | 7 | skinparam note { 8 | BorderColor Green 9 | } 10 | 11 | Person(npu, "Privileged / Nonprivileged User", "A Pages Admin / Customer") 12 | 13 | note "Auth: OAuth 2.0\nvia Github MFA" as githubpagesauth 14 | 15 | Boundary(awsgov, "AWS GovCloud") { 16 | Boundary(cloudgov, "cloud.gov Platform") { 17 | System_Inherited(elb, "Load Balancer / Router", "cloud.gov") 18 | System(core, "Pages Web", "//[Node JS]//") 19 | Db_Shared(db, "Postgres", "AWS RDS") 20 | Db_Shared(redis, "Redis", "cloud.gov Redis") 21 | } 22 | } 23 | 24 | Boundary(gsa, "GSA Authorized SaaS") { 25 | System_Ext(newrelic, "New Relic", "Monitoring SaaS") 26 | System_Ext(dap, "DAP", "Analytics collection") 27 | } 28 | 29 | HTTPS(npu, elb, "1. requests content") 30 | HTTP_Variable(elb, core, "2. proxies request") 31 | 32 | TCPS_Variable(core, db, "3. reads/writes site metadata & configuration") 33 | note on link 34 | Auth: Credentials/Network 35 | end note 36 | 37 | TCPS_Variable(core, redis, "reads/writes notifications") 38 | note on link 39 | Auth: Credentials 40 | end note 41 | 42 | TCPS(core, newrelic, "reports telemetry") 43 | note on link 44 | Auth: Token 45 | end note 46 | 47 | HTTPS(npu, dap, "reports usage") 48 | 49 | ' Authentication annotations 50 | npu .. githubpagesauth 51 | githubpagesauth .. core 52 | @enduml 53 | -------------------------------------------------------------------------------- /source/diagrams/webapp_B.puml: -------------------------------------------------------------------------------- 1 | @startuml 2 | !include ssp.puml 3 | 4 | hide stereotypes 5 | skinparam note { 6 | BorderColor Green 7 | } 8 | 9 | Person(npu, "Privileged / Nonprivileged User", "A Pages Admin / Customer") 10 | 11 | 12 | Boundary(awsgov, "AWS GovCloud") { 13 | Boundary(cloudgov, "cloud.gov Platform") { 14 | note "Auth: OAuth 2.0 \n via cloud.gov MFA" as githubpagesauth 15 | System_Inherited(elb, "Load Balancer / Router", "cloud.gov") 16 | System_Inherited(prom, "Prometheus", "Monitoring Service") 17 | System(core, "Pages WebApp", "//[Node JS]//") 18 | Db_Shared(db, "Postgres", "AWS RDS") 19 | Db_Shared(redis, "Redis", "cloud.gov Redis") 20 | } 21 | } 22 | 23 | Boundary(gsa, "GSA Authorized SaaS") { 24 | System_Ext(dap, "DAP", "Analytics collection") 25 | System_Ext(newrelic, "New Relic", "Monitoring SaaS") 26 | } 27 | 28 | HTTPS(npu, elb, "1. requests content") 29 | HTTP_Variable(elb, core, "2. proxies request") 30 | 31 | TCPS_Variable(core, db, "3. reads/writes site metadata & configuration") 32 | note on link 33 | Auth: Credentials/Network 34 | end note 35 | 36 | TCPS_Variable(core, redis, "reads/writes notifications") 37 | note on link 38 | Auth: Credentials 39 | end note 40 | 41 | TCPS(prom, core, "monitors health") 42 | note on link 43 | Auth: Token 44 | end note 45 | 46 | HTTPS(npu, dap, "reports usage") 47 | 48 | HTTPS(core, newrelic, "Uptime monitor") 49 | note on link 50 | No Auth Needed 51 | end note 52 | 53 | ' Authentication annotations 54 | npu .. githubpagesauth 55 | githubpagesauth .. core 56 | @enduml 57 | -------------------------------------------------------------------------------- /source/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | cloud.gov Diagrams 6 | 7 | 8 | 9 |

cloud.gov Diagrams

10 |
    11 | {{ #diagram-list }} 12 |
  • 13 | {{ name }} 14 | {{ description }} 15 |
  • 16 | {{ /diagram-list }} 17 |
18 |

See cg-diagrams for source code and issue tracker.

19 | 20 | 21 | -------------------------------------------------------------------------------- /source/html/render.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {{ diagram-title }} 6 | 7 | 8 | 9 | 10 | Back to all diagrams 11 | Save as PNG 12 |
13 | {{ diagram-contents }} 14 |
15 | 16 | 17 |
18 | 20 | 21 | 22 | 23 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
32 |
33 |
34 | 36 | Legend 37 | 38 |
39 |
40 | 41 | 42 | 44 | 45 | 46 | 49 | 50 | 53 | 55 | 56 | 57 | 58 | 59 | 63 | 64 | 65 | 68 | 70 | 71 | 72 | 73 | 74 | 75 | 77 | 78 | 79 |
80 | Bidirectional data/information 81 | flow 82 |
83 |
84 |
85 |
86 | 88 | 89 | 90 |
91 | One-directional data/information 92 | flow 93 |
94 |
95 |
96 |
97 | 99 | 100 | 101 |
102 | Data/information request that is system generated 103 |
104 |
105 |
106 |
107 | 109 | 110 | 111 |
112 | 113 | Component ( square corners ) 114 | 115 |
116 |
117 |
118 |
119 | 121 | 122 | 123 |
124 | 125 | Collections of VMs or containers 126 | 127 |
128 |
129 |
130 |
131 | 133 | 134 | 135 |
136 | 137 | Non-VMs / container components ( rounded corners ) 138 | 139 |
140 |
141 |
142 |
143 | 145 | 146 | 147 |
148 | 149 | User types 150 | 151 |
152 |
153 |
154 |
155 | 157 | 158 | 159 |
160 | 161 | External data components 162 | 163 |
164 |
165 |
166 |
167 | 169 | 170 | 171 |
172 | 173 | Grouping of components 174 | 175 |
176 |
177 |
178 |
179 |
180 | 181 | 183 | 185 | 186 | 188 | 190 | 191 | 193 | 195 | 196 | 198 | 200 | 201 | 203 | 205 | 206 | 208 | 210 | 211 | 212 |
213 |
214 |
215 | 216 | Back to all diagrams 217 | 218 | 219 | 220 | -------------------------------------------------------------------------------- /source/javascript/start.js: -------------------------------------------------------------------------------- 1 | import * as mermaid from 'mermaid/dist/mermaid.esm.min.mjs'; 2 | import * as svgPng from 'save-svg-as-png'; 3 | 4 | // TODO This is very ugly, but for now it renders. This SVG creation should be 5 | // done in the build step. 6 | let ss = document.getElementById( 'js-stage' ); 7 | 8 | let btn = document.getElementById( 'save-png-button' ); 9 | 10 | btn.addEventListener('click', function() { 11 | let svgList = ss.getElementsByTagName('svg'); 12 | let options = { 13 | scale: 2, 14 | backgroundColor: '#ffffff', 15 | }; 16 | if (svgList.length) { 17 | svgPng.saveSvgAsPng(svgList[0], document.title+'.png', options); 18 | } 19 | }); 20 | 21 | mermaid.mermaidAPI.render( 22 | 'js-stage', 23 | ss.textContent.replace(/\n/g, '\\n'), 24 | function ( c ) { 25 | ss.innerHTML = c; 26 | } 27 | ); 28 | -------------------------------------------------------------------------------- /source/styles/_mermaid.scss: -------------------------------------------------------------------------------- 1 | /* Flowchart variables */ 2 | /* Sequence Diagram variables */ 3 | /* Gantt chart variables */ 4 | .mermaid .label { 5 | color: #333; 6 | } 7 | .node rect, 8 | .node circle, 9 | .node ellipse, 10 | .node polygon { 11 | fill: #ECECFF; 12 | stroke: #CCCCFF; 13 | stroke-width: 1px; 14 | } 15 | .edgePath .path { 16 | stroke: #333333; 17 | } 18 | .edgeLabel { 19 | background-color: #e8e8e8; 20 | } 21 | .cluster rect { 22 | fill: #ffffde !important; 23 | rx: 4 !important; 24 | stroke: #aaaa33 !important; 25 | stroke-width: 1px !important; 26 | } 27 | .cluster text { 28 | fill: #333; 29 | } 30 | .actor { 31 | stroke: #CCCCFF; 32 | fill: #ECECFF; 33 | } 34 | text.actor { 35 | fill: black; 36 | stroke: none; 37 | } 38 | .actor-line { 39 | stroke: grey; 40 | } 41 | .messageLine0 { 42 | stroke-width: 1.5; 43 | stroke-dasharray: "2 2"; 44 | marker-end: "url(#arrowhead)"; 45 | stroke: #333; 46 | } 47 | .messageLine1 { 48 | stroke-width: 1.5; 49 | stroke-dasharray: "2 2"; 50 | stroke: #333; 51 | } 52 | #arrowhead { 53 | fill: #333; 54 | } 55 | #crosshead path { 56 | fill: #333 !important; 57 | stroke: #333 !important; 58 | } 59 | .messageText { 60 | fill: #333; 61 | stroke: none; 62 | } 63 | .labelBox { 64 | stroke: #CCCCFF; 65 | fill: #ECECFF; 66 | } 67 | .labelText { 68 | fill: black; 69 | stroke: none; 70 | } 71 | .loopText { 72 | fill: black; 73 | stroke: none; 74 | } 75 | .loopLine { 76 | stroke-width: 2; 77 | stroke-dasharray: "2 2"; 78 | marker-end: "url(#arrowhead)"; 79 | stroke: #CCCCFF; 80 | } 81 | .note { 82 | stroke: #aaaa33; 83 | fill: #fff5ad; 84 | } 85 | .noteText { 86 | fill: black; 87 | stroke: none; 88 | font-family: 'trebuchet ms', verdana, arial; 89 | font-size: 14px; 90 | } 91 | /** Section styling */ 92 | .section { 93 | stroke: none; 94 | opacity: 0.2; 95 | } 96 | .section0 { 97 | fill: rgba(102, 102, 255, 0.49); 98 | } 99 | .section2 { 100 | fill: #fff400; 101 | } 102 | .section1, 103 | .section3 { 104 | fill: white; 105 | opacity: 0.2; 106 | } 107 | .sectionTitle0 { 108 | fill: #333; 109 | } 110 | .sectionTitle1 { 111 | fill: #333; 112 | } 113 | .sectionTitle2 { 114 | fill: #333; 115 | } 116 | .sectionTitle3 { 117 | fill: #333; 118 | } 119 | .sectionTitle { 120 | text-anchor: start; 121 | font-size: 11px; 122 | text-height: 14px; 123 | } 124 | /* Grid and axis */ 125 | .grid .tick { 126 | stroke: lightgrey; 127 | opacity: 0.3; 128 | shape-rendering: crispEdges; 129 | } 130 | .grid path { 131 | stroke-width: 0; 132 | } 133 | /* Today line */ 134 | .today { 135 | fill: none; 136 | stroke: red; 137 | stroke-width: 2px; 138 | } 139 | /* Task styling */ 140 | /* Default task */ 141 | .task { 142 | stroke-width: 2; 143 | } 144 | .taskText { 145 | text-anchor: middle; 146 | font-size: 11px; 147 | } 148 | .taskTextOutsideRight { 149 | fill: black; 150 | text-anchor: start; 151 | font-size: 11px; 152 | } 153 | .taskTextOutsideLeft { 154 | fill: black; 155 | text-anchor: end; 156 | font-size: 11px; 157 | } 158 | /* Specific task settings for the sections*/ 159 | .taskText0, 160 | .taskText1, 161 | .taskText2, 162 | .taskText3 { 163 | fill: white; 164 | } 165 | .task0, 166 | .task1, 167 | .task2, 168 | .task3 { 169 | fill: #8a90dd; 170 | stroke: #534fbc; 171 | } 172 | .taskTextOutside0, 173 | .taskTextOutside2 { 174 | fill: black; 175 | } 176 | .taskTextOutside1, 177 | .taskTextOutside3 { 178 | fill: black; 179 | } 180 | /* Active task */ 181 | .active0, 182 | .active1, 183 | .active2, 184 | .active3 { 185 | fill: #bfc7ff; 186 | stroke: #534fbc; 187 | } 188 | .activeText0, 189 | .activeText1, 190 | .activeText2, 191 | .activeText3 { 192 | fill: black !important; 193 | } 194 | /* Completed task */ 195 | .done0, 196 | .done1, 197 | .done2, 198 | .done3 { 199 | stroke: grey; 200 | fill: lightgrey; 201 | stroke-width: 2; 202 | } 203 | .doneText0, 204 | .doneText1, 205 | .doneText2, 206 | .doneText3 { 207 | fill: black !important; 208 | } 209 | /* Tasks on the critical line */ 210 | .crit0, 211 | .crit1, 212 | .crit2, 213 | .crit3 { 214 | stroke: #ff8888; 215 | fill: red; 216 | stroke-width: 2; 217 | } 218 | .activeCrit0, 219 | .activeCrit1, 220 | .activeCrit2, 221 | .activeCrit3 { 222 | stroke: #ff8888; 223 | fill: #bfc7ff; 224 | stroke-width: 2; 225 | } 226 | .doneCrit0, 227 | .doneCrit1, 228 | .doneCrit2, 229 | .doneCrit3 { 230 | stroke: #ff8888; 231 | fill: lightgrey; 232 | stroke-width: 2; 233 | cursor: pointer; 234 | shape-rendering: crispEdges; 235 | } 236 | .doneCritText0, 237 | .doneCritText1, 238 | .doneCritText2, 239 | .doneCritText3 { 240 | fill: black !important; 241 | } 242 | .activeCritText0, 243 | .activeCritText1, 244 | .activeCritText2, 245 | .activeCritText3 { 246 | fill: black !important; 247 | } 248 | .titleText { 249 | text-anchor: middle; 250 | font-size: 18px; 251 | fill: black; 252 | } 253 | /* 254 | 255 | 256 | */ 257 | .node text { 258 | font-family: 'trebuchet ms', verdana, arial; 259 | font-size: 14px; 260 | } 261 | div.mermaidTooltip { 262 | position: absolute; 263 | text-align: center; 264 | max-width: 200px; 265 | padding: 2px; 266 | font-family: 'trebuchet ms', verdana, arial; 267 | font-size: 12px; 268 | background: #ffffde; 269 | border: 1px solid #aaaa33; 270 | border-radius: 2px; 271 | pointer-events: none; 272 | z-index: 100; 273 | } 274 | -------------------------------------------------------------------------------- /source/styles/_shell.scss: -------------------------------------------------------------------------------- 1 | html { 2 | background-color: #ffffff; 3 | } 4 | 5 | body { 6 | background-color: color('base-lightest'); 7 | margin: 5%; 8 | padding: 2.5%; 9 | } 10 | 11 | .scuttle-stage { 12 | margin: 5% 0; 13 | } 14 | 15 | /** 16 | * Diagram list for the Homepage 17 | */ 18 | .scuttle-diagram-list { 19 | margin: 2.5%; 20 | } 21 | 22 | .scuttle-diagram-list__item { 23 | // Necessary because of the Draft US Web Design Standards 24 | &::before { 25 | content: ''; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /source/styles/render.scss: -------------------------------------------------------------------------------- 1 | // Draft US Web Design Standards 2 | @import '../../node_modules/uswds/dist/scss/uswds.scss'; 3 | @import '../../node_modules/font-awesome/scss/font-awesome.scss'; 4 | @import './mermaid'; 5 | @import './shell'; 6 | 7 | .scuttle-stage, 8 | .scuttle-legend { 9 | background: $theme-color-base-lightest; 10 | 11 | font-family: $theme-font-role-body; 12 | 13 | .label { 14 | color: #ffffff; 15 | 16 | overflow-wrap: break-word; 17 | word-break: break-word; 18 | } 19 | } 20 | 21 | .scuttle-stage { 22 | overflow-x: scroll; 23 | min-height: 999px; 24 | } 25 | 26 | .scuttle-legend .edgeLabel { 27 | line-height: 1.75; 28 | } 29 | 30 | .cluster { 31 | rect { 32 | fill: $theme-color-base-lightest !important; 33 | stroke: $theme-color-primary !important; 34 | stroke-width: 2px !important; 35 | } 36 | 37 | text { 38 | @include h4; 39 | font-family: 'Source Sans Pro', 'Helvetica Neue', 'Helvetica', 'Roboto', 40 | 'Arial', sans-serif; 41 | font-size: 17px; 42 | } 43 | } 44 | 45 | .node rect, 46 | .node circle, 47 | .node ellipse, 48 | .node polygon { 49 | fill: $theme-color-primary; 50 | stroke: $theme-color-primary-darker; 51 | stroke-width: 2px; 52 | } 53 | 54 | .node .label { 55 | font-family: 'Source Sans Pro', 'Helvetica Neue', 'Helvetica', 'Roboto', 56 | 'Arial', sans-serif; 57 | color: rgb(255, 255, 255); 58 | } 59 | 60 | .edgePath .path { 61 | stroke: color('primary-darker') !important; 62 | stroke-width: 2px !important; 63 | } 64 | 65 | .edgePath marker path { 66 | fill: color('primary-darker') !important; 67 | } 68 | 69 | .edgeLabel { 70 | background-color: #ffffff; 71 | border: #ffffff 5px solid; 72 | color: color('ink'); 73 | &:empty { 74 | border: none; 75 | } 76 | font-family: 'Source Sans Pro', 'Helvetica Neue', 'Helvetica', 'Roboto', 77 | 'Arial', sans-serif; 78 | font-family: 17px; 79 | } 80 | 81 | rect { 82 | fill: color('primary'); 83 | stroke: color('primary-darker'); 84 | stroke-width: 2px; 85 | 86 | &.note { 87 | fill: color('primary-lighter'); 88 | stroke: color('primary-light'); 89 | stroke-width: 2px; 90 | } 91 | 92 | &.labelBox { 93 | fill: color('primary-dark'); 94 | stroke: color('primary'); 95 | } 96 | 97 | &.actor { 98 | fill: color('primary'); 99 | stroke: color('primary-darker'); 100 | } 101 | } 102 | 103 | #crosshead, 104 | #arrowhead { 105 | path { 106 | fill: color('primary-darker'); 107 | } 108 | } 109 | 110 | line { 111 | &[class^='messageLine'], 112 | &.actor-line { 113 | fill: color('primary-darker'); 114 | stroke: color('primary-darker'); 115 | stroke-width: 2px; 116 | } 117 | 118 | &.loopLine { 119 | fill: color('primary-darker'); 120 | stroke: color('primary'); 121 | stroke-width: 2px; 122 | } 123 | } 124 | 125 | text { 126 | &.messageText { 127 | font-family: $theme-font-role-code; 128 | text-shadow: 2px 2px 0 #ffffff, 1px 1px 0 color('base-light'); 129 | fill: color('primary-darker'); 130 | font-size: 1rem; 131 | } 132 | 133 | &.actor { 134 | fill: #ffffff; 135 | } 136 | 137 | &.noteText { 138 | fill: color('base'); 139 | font-size: 1.25rem; 140 | } 141 | 142 | &.labelText { 143 | font-family: $theme-font-role-alt; 144 | fill: color('base-lighter'); 145 | font-size: 1.25rem; 146 | text-transform: uppercase; 147 | } 148 | 149 | &.loopText { 150 | font-family: $theme-font-role-alt; 151 | font-size: 1rem; 152 | font-style: oblique; 153 | } 154 | } 155 | --------------------------------------------------------------------------------