├── .dockerignore ├── .editorconfig ├── .eslintignore ├── .eslintrc ├── .flowconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── stale.yml ├── .gitignore ├── .prettierrc ├── .stylelintrc ├── .testcafe-electron-rc ├── .travis.yml ├── .vscode └── settings.json ├── CHANGELOG.md ├── LICENSE ├── README.md ├── app ├── Routes.js ├── app.global.css ├── app.html ├── app.icns ├── clients │ └── aws.js ├── components │ ├── CreationForm.js │ ├── CreationFormButton.js │ ├── DeleteButton.js │ ├── Home.css │ ├── Home.js │ ├── SearchTree.js │ ├── SettingsButton.js │ └── formDataShape.propType.js ├── constants │ └── routes.json ├── containers │ ├── App.js │ └── Root.js ├── ducks │ ├── index.js │ └── parameters.js ├── index.js ├── main.dev.js ├── menu.js ├── store │ ├── configureStore.dev.js │ ├── configureStore.js │ ├── configureStore.prod.js │ └── localStore.js └── utils │ ├── .gitkeep │ └── filters.js ├── appveyor.yml ├── babel.config.js ├── configs ├── webpack.config.base.js ├── webpack.config.eslint.js ├── webpack.config.main.prod.babel.js ├── webpack.config.renderer.dev.babel.js ├── webpack.config.renderer.dev.dll.babel.js └── webpack.config.renderer.prod.babel.js ├── dev-app-update.yml ├── flow-typed └── module_vx.x.x.js ├── internals ├── flow │ ├── CSSModule.js.flow │ └── WebpackAsset.js.flow ├── img │ ├── eslint-padded-90.png │ ├── eslint-padded.png │ ├── eslint.png │ ├── flow-padded-90.png │ ├── flow-padded.png │ ├── flow.png │ ├── jest-padded-90.png │ ├── jest-padded.png │ ├── jest.png │ ├── js-padded.png │ ├── js.png │ ├── npm.png │ ├── react-padded-90.png │ ├── react-padded.png │ ├── react-router-padded-90.png │ ├── react-router-padded.png │ ├── react-router.png │ ├── react.png │ ├── redux-padded-90.png │ ├── redux-padded.png │ ├── redux.png │ ├── webpack-padded-90.png │ ├── webpack-padded.png │ ├── webpack.png │ ├── yarn-padded-90.png │ ├── yarn-padded.png │ └── yarn.png ├── mocks │ └── fileMock.js └── scripts │ ├── CheckBuiltsExist.js │ ├── CheckNodeEnv.js │ └── CheckPortInUse.js ├── package.json ├── renovate.json ├── resources ├── icon.icns ├── icon.ico ├── icon.png ├── icons │ ├── 1024x1024.png │ ├── 128x128.png │ ├── 16x16.png │ ├── 24x24.png │ ├── 256x256.png │ ├── 32x32.png │ ├── 48x48.png │ ├── 512x512.png │ ├── 64x64.png │ └── 96x96.png └── screenshot.png ├── test ├── .eslintrc └── example.js └── yarn.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | .eslintcache 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # OSX 31 | .DS_Store 32 | 33 | # flow-typed 34 | flow-typed/npm/* 35 | !flow-typed/npm/module_vx.x.x.js 36 | 37 | # App packaged 38 | release 39 | app/main.prod.js 40 | app/main.prod.js.map 41 | app/renderer.prod.js 42 | app/renderer.prod.js.map 43 | app/style.css 44 | app/style.css.map 45 | dist 46 | dll 47 | main.js 48 | main.js.map 49 | 50 | .idea 51 | npm-debug.log.* 52 | .*.dockerfile -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | .eslintcache 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # OSX 31 | .DS_Store 32 | 33 | # flow-typed 34 | flow-typed/npm/* 35 | !flow-typed/npm/module_vx.x.x.js 36 | 37 | # App packaged 38 | release 39 | app/main.prod.js 40 | app/main.prod.js.map 41 | app/renderer.prod.js 42 | app/renderer.prod.js.map 43 | app/style.css 44 | app/style.css.map 45 | dist 46 | dll 47 | main.js 48 | main.js.map 49 | 50 | .idea 51 | npm-debug.log.* 52 | __snapshots__ 53 | 54 | # Package.json 55 | package.json 56 | .travis.yml 57 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parser": "babel-eslint", 3 | "parserOptions": { 4 | "sourceType": "module", 5 | "allowImportExportEverywhere": true 6 | }, 7 | "extends": ["airbnb", "prettier", "prettier/flowtype", "prettier/react"], 8 | "env": { 9 | "browser": true, 10 | "node": true 11 | }, 12 | "rules": { 13 | "arrow-parens": ["off"], 14 | "compat/compat": "error", 15 | "consistent-return": "off", 16 | "comma-dangle": "off", 17 | "flowtype/boolean-style": ["error", "boolean"], 18 | "flowtype/define-flow-type": "warn", 19 | "flowtype/delimiter-dangle": ["error", "never"], 20 | "flowtype/generic-spacing": ["error", "never"], 21 | "flowtype/no-primitive-constructor-types": "error", 22 | "flowtype/no-weak-types": "warn", 23 | "flowtype/object-type-delimiter": ["error", "comma"], 24 | "flowtype/require-parameter-type": "off", 25 | "flowtype/require-return-type": "off", 26 | "flowtype/require-valid-file-annotation": "off", 27 | "flowtype/semi": ["error", "always"], 28 | "flowtype/space-after-type-colon": ["error", "always"], 29 | "flowtype/space-before-generic-bracket": ["error", "never"], 30 | "flowtype/space-before-type-colon": ["error", "never"], 31 | "flowtype/union-intersection-spacing": ["error", "always"], 32 | "flowtype/use-flow-type": "error", 33 | "flowtype/valid-syntax": "error", 34 | "generator-star-spacing": "off", 35 | "import/no-unresolved": "error", 36 | "import/no-extraneous-dependencies": "off", 37 | "jsx-a11y/anchor-is-valid": "off", 38 | "no-console": "off", 39 | "no-use-before-define": "off", 40 | "no-multi-assign": "off", 41 | "promise/param-names": "error", 42 | "promise/always-return": "error", 43 | "promise/catch-or-return": "error", 44 | "promise/no-native": "off", 45 | "react/sort-comp": [ 46 | "error", 47 | { 48 | "order": [ 49 | "type-annotations", 50 | "static-methods", 51 | "lifecycle", 52 | "everything-else", 53 | "render" 54 | ] 55 | } 56 | ], 57 | "react/jsx-no-bind": "off", 58 | "react/jsx-filename-extension": [ 59 | "error", 60 | { "extensions": [".js", ".jsx"] } 61 | ], 62 | "react/prefer-stateless-function": "off" 63 | }, 64 | "plugins": ["flowtype", "import", "promise", "compat", "react"], 65 | "settings": { 66 | "import/resolver": { 67 | "webpack": { 68 | "config": "configs/webpack.config.eslint.js" 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /app/main.prod.js 3 | /app/main.prod.js.map 4 | /app/dist/.* 5 | /resources/.* 6 | /node_modules/webpack-cli 7 | /release/.* 8 | /dll/.* 9 | /release/.* 10 | /git/.* 11 | 12 | [include] 13 | 14 | [libs] 15 | 16 | [options] 17 | esproposal.class_static_fields=enable 18 | esproposal.class_instance_fields=enable 19 | esproposal.export_star_as=enable 20 | module.name_mapper.extension='css' -> '/internals/flow/CSSModule.js.flow' 21 | module.name_mapper.extension='styl' -> '/internals/flow/CSSModule.js.flow' 22 | module.name_mapper.extension='scss' -> '/internals/flow/CSSModule.js.flow' 23 | module.name_mapper.extension='png' -> '/internals/flow/WebpackAsset.js.flow' 24 | module.name_mapper.extension='jpg' -> '/internals/flow/WebpackAsset.js.flow' 25 | suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe 26 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue 27 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text eol=lf 2 | *.png binary 3 | *.jpg binary 4 | *.jpeg binary 5 | *.ico binary 6 | *.icns binary 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## Prerequisites 4 | 5 | - [ ] Using yarn 6 | - [ ] Using an up-to-date master branch 7 | - [ ] Using latest version of devtools. See [wiki for howto update](https://github.com/electron-react-boilerplate/electron-react-boilerplate/wiki/DevTools) 8 | - [ ] Link to stacktrace in a Gist (for bugs) 9 | - [ ] For issue in production release, devtools output of `DEBUG_PROD=true yarn build && yarn start` 10 | - [ ] Tried solutions mentioned in [#400](https://github.com/electron-react-boilerplate/electron-react-boilerplate/issues/400) 11 | 12 | ## Expected Behavior 13 | 14 | 15 | 16 | 17 | ## Current Behavior 18 | 19 | 20 | 21 | 22 | ## Possible Solution 23 | 24 | 25 | 26 | 27 | ## Steps to Reproduce (for bugs) 28 | 29 | 30 | 31 | 32 | 1. 33 | 34 | 2. 35 | 36 | 3. 37 | 38 | 4. 39 | 40 | ## Context 41 | 42 | 43 | 44 | 45 | 46 | ## Your Environment 47 | 48 | 49 | 50 | - Node version : 51 | - Version or Branch used : 52 | - Operating System and version : 53 | - Link to your project : 54 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Number of days of inactivity before an issue becomes stale 2 | daysUntilStale: 60 3 | # Number of days of inactivity before a stale issue is closed 4 | daysUntilClose: 7 5 | # Issues with these labels will never be considered stale 6 | exemptLabels: 7 | - pr 8 | - discussion 9 | - e2e 10 | - enhancement 11 | # Comment to post when marking an issue as stale. Set to `false` to disable 12 | markComment: > 13 | This issue has been automatically marked as stale because it has not had 14 | recent activity. It will be closed if no further activity occurs. Thank you 15 | for your contributions. 16 | # Comment to post when closing a stale issue. Set to `false` to disable 17 | closeComment: false 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | .eslintcache 25 | 26 | # Dependency directory 27 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 28 | node_modules 29 | 30 | # OSX 31 | .DS_Store 32 | 33 | # flow-typed 34 | flow-typed/npm/* 35 | !flow-typed/npm/module_vx.x.x.js 36 | 37 | # App packaged 38 | release 39 | app/main.prod.js 40 | app/main.prod.js.map 41 | app/renderer.prod.js 42 | app/renderer.prod.js.map 43 | app/style.css 44 | app/style.css.map 45 | dist 46 | dll 47 | main.js 48 | main.js.map 49 | 50 | .idea 51 | npm-debug.log.* 52 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "overrides": [ 3 | { 4 | "files": [".prettierrc", ".babelrc", ".eslintrc", ".stylelintrc"], 5 | "options": { 6 | "parser": "json" 7 | } 8 | } 9 | ], 10 | "singleQuote": true 11 | } 12 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard", "stylelint-config-prettier"] 3 | } 4 | -------------------------------------------------------------------------------- /.testcafe-electron-rc: -------------------------------------------------------------------------------- 1 | { 2 | "mainWindowUrl": "./app/app.html", 3 | "appPath": "." 4 | } 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | matrix: 2 | allow_failures: 3 | - os: windows 4 | include: 5 | - os: osx 6 | language: node_js 7 | node_js: 8 | - node 9 | env: 10 | - ELECTRON_CACHE=$HOME/.cache/electron 11 | - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder 12 | 13 | - os: linux 14 | language: node_js 15 | node_js: 16 | - node 17 | addons: 18 | apt: 19 | sources: 20 | - ubuntu-toolchain-r-test 21 | packages: 22 | - gcc-multilib 23 | - g++-8 24 | - g++-multilib 25 | - icnsutils 26 | - graphicsmagick 27 | - xz-utils 28 | - xorriso 29 | - rpm 30 | 31 | - os: windows 32 | language: node_js 33 | node_js: 34 | - node 35 | env: 36 | - ELECTRON_CACHE=$HOME/.cache/electron 37 | - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder 38 | 39 | before_cache: 40 | - rm -rf $HOME/.cache/electron-builder/wine 41 | 42 | cache: 43 | yarn: true 44 | directories: 45 | - node_modules 46 | - $(npm config get prefix)/lib/node_modules 47 | - flow-typed 48 | - $HOME/.cache/electron 49 | - $HOME/.cache/electron-builder 50 | 51 | before_install: 52 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then export CXX="g++-8"; fi 53 | 54 | install: 55 | - yarn --ignore-engines 56 | # On Linux, initialize "virtual display". See before_script 57 | - | 58 | if [ "$TRAVIS_OS_NAME" == "linux" ]; then 59 | /sbin/start-stop-daemon \ 60 | --start \ 61 | --quiet \ 62 | --pidfile /tmp/custom_xvfb_99.pid \ 63 | --make-pidfile \ 64 | --background \ 65 | --exec /usr/bin/Xvfb \ 66 | -- :99 -ac -screen 0 1280x1024x16 67 | else 68 | : 69 | fi 70 | services: 71 | - xvfb 72 | script: 73 | - yarn package-ci 74 | - yarn lint 75 | # - yarn flow 76 | # HACK: Temporarily ignore `yarn test` on linux 77 | # - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then yarn test; fi 78 | - yarn build-e2e 79 | # - yarn test-e2e 80 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | ".babelrc": "jsonc", 4 | ".eslintrc": "jsonc", 5 | ".prettierrc": "jsonc", 6 | 7 | ".stylelintrc": "json", 8 | 9 | ".dockerignore": "ignore", 10 | ".eslintignore": "ignore", 11 | ".flowconfig": "ignore" 12 | }, 13 | 14 | "javascript.validate.enable": false, 15 | "javascript.format.enable": false, 16 | "typescript.validate.enable": false, 17 | "typescript.format.enable": false, 18 | 19 | "flow.useNPMPackagedFlow": true, 20 | "search.exclude": { 21 | ".git": true, 22 | ".eslintcache": true, 23 | "app/dist": true, 24 | "app/main.prod.js": true, 25 | "app/main.prod.js.map": true, 26 | "bower_components": true, 27 | "dll": true, 28 | "flow-typed": true, 29 | "release": true, 30 | "node_modules": true, 31 | "npm-debug.log.*": true, 32 | "test/**/__snapshots__": true, 33 | "yarn.lock": true 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ### Changelog 2 | 3 | All notable changes to this project will be documented in this file. Dates are displayed in UTC. 4 | 5 | Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog). 6 | 7 | #### [v0.5.1](https://github.com/smblee/parameter-store-manager/compare/v0.5.0...v0.5.1) 8 | 9 | > 5 September 2019 10 | 11 | - Use credential provider chain to allow credentials_process [`#102`](https://github.com/smblee/parameter-store-manager/pull/102) 12 | - Feature/aws profile [`#76`](https://github.com/smblee/parameter-store-manager/pull/76) 13 | - Bump fstream from 1.0.11 to 1.0.12 [`#75`](https://github.com/smblee/parameter-store-manager/pull/75) 14 | - version bumped to 0.5.0, auto update to auto update and notify, changelog added [`#31`](https://github.com/smblee/parameter-store-manager/pull/31) 15 | 16 | #### [v0.5.0](https://github.com/smblee/parameter-store-manager/compare/v0.2.1...v0.5.0) 17 | 18 | > 3 May 2019 19 | 20 | - Feature/removing develop branch [`#25`](https://github.com/smblee/parameter-store-manager/pull/25) 21 | - map fix [`#24`](https://github.com/smblee/parameter-store-manager/pull/24) 22 | - V0.3.0 [`#18`](https://github.com/smblee/parameter-store-manager/pull/18) 23 | - readme and changelog [`1e0ae81`](https://github.com/smblee/parameter-store-manager/commit/1e0ae814b4e43524e6df503e37b2870ab6730686) 24 | - adding description and screenshot [`8908195`](https://github.com/smblee/parameter-store-manager/commit/89081953871f3f94b38134eb6c5c2e8f593bd228) 25 | 26 | #### [v0.2.1](https://github.com/smblee/parameter-store-manager/compare/v0.2.0...v0.2.1) 27 | 28 | > 19 April 2019 29 | 30 | - 0.2.1 bump [`1985aff`](https://github.com/smblee/parameter-store-manager/commit/1985aff6df11fb53d45e2e744d031672749e0d21) 31 | 32 | #### [v0.2.0](https://github.com/smblee/parameter-store-manager/compare/v0.1.5...v0.2.0) 33 | 34 | > 19 April 2019 35 | 36 | - 0.1.6 version check on menu click [`97ba2ae`](https://github.com/smblee/parameter-store-manager/commit/97ba2ae9c44f88cb34181192cf50fcc7c91f5d84) 37 | - unique-fy parameters on change [`f8b848e`](https://github.com/smblee/parameter-store-manager/commit/f8b848e078a825fb27281eca110aa35c4bab0bce) 38 | - 0.2.0 release [`b1f0e07`](https://github.com/smblee/parameter-store-manager/commit/b1f0e0728701db512b4e8078f1cb51de483bbf2a) 39 | 40 | #### [v0.1.5](https://github.com/smblee/parameter-store-manager/compare/v0.1.3...v0.1.5) 41 | 42 | > 19 April 2019 43 | 44 | - bumping to 0.1.4 and handling auto updates [`370365e`](https://github.com/smblee/parameter-store-manager/commit/370365e2d9e882249efad4aef893aef3efbf372b) 45 | - 0.1.5 final version fix [`14bbe5c`](https://github.com/smblee/parameter-store-manager/commit/14bbe5c62910be0d773f4ab6935177eecc633278) 46 | 47 | #### v0.1.3 48 | 49 | > 19 April 2019 50 | 51 | - first commit [`2606126`](https://github.com/smblee/parameter-store-manager/commit/26061267dd499bf0c4c73ad3941192a63975f31e) 52 | - bumping to 0.1.1 [`db081c0`](https://github.com/smblee/parameter-store-manager/commit/db081c0885a4f27c9e100300c822dc626f7d270b) 53 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015-present C. T. Lin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Parameter Store Manager 2 | 3 | Are you tired of the AWS Console yet? Can't figure out `name` `starts-with` vs `path` `recursive` when searching for parameters? 4 | 5 | #### Parameter Store Manager is a desktop application that helps users easily view/search/manage AWS parameter store parameters. 6 | 7 | ![alt text](https://raw.githubusercontent.com/smblee/parameter-store-manager/master/resources/screenshot.png) 8 | 9 | Built with `electron-react-boilerplate`. 10 | 11 | ## Quick Start 12 | - Download the binary here (Supports Windows, MacOS, Linux): https://github.com/smblee/parameter-store-manager/releases 13 | - Set up AWS Credentials (there are several ways to do this. E.g. `~/.aws/credentials` method) https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials 14 | - Run the downloaded binary! 15 | 16 | ## Current Features 17 | 18 | - View parameters: Tree view, list view 19 | - Filter parameters: Filter by keyword (with highlighting) 20 | - Search parameters: by path (glob (\*, \*\*) supported) 21 | - e.g. `/path/**/*Url` 22 | - e.g. `*parameter` 23 | - Add new parameters 24 | - Service parameter (assuming path `/services/{environments}/{serviceName}/{parameterName}`) 25 | - Generic parameter 26 | - Supports `String`, `SecureString` (no `StringList` support atm) 27 | - Supports KMS Key Encryption for `SecureString` 28 | - Edit parameter 29 | - Change the description, value 30 | - Change from/to `String` and `SecureString` 31 | - Duplicate parameter 32 | - Opens the `add new parameters` flow with the values pre-filled. 33 | - Delete parameter 34 | - Copy parameter values with one click 35 | - Refetch/refresh parameters 36 | - Program Auto Updater/Update checker (Buggy?) 37 | 38 | ## Run 39 | 40 | Start the app in the `dev` environment. This starts the renderer process in [**hot-module-replacement**](https://webpack.js.org/guides/hmr-react/) mode and starts a webpack dev server that sends hot updates to the renderer process: 41 | 42 | ```bash 43 | $ yarn dev 44 | ``` 45 | 46 | If you don't need autofocus when your files was changed, then run `dev` with env `START_MINIMIZED=true`: 47 | 48 | ```bash 49 | $ START_MINIMIZED=true yarn dev 50 | ``` 51 | 52 | ## Packaging 53 | 54 | To package apps for the local platform: 55 | 56 | ```bash 57 | $ yarn package 58 | ``` 59 | 60 | To package apps for all platforms: 61 | 62 | First, refer to the [Multi Platform Build docs](https://www.electron.build/multi-platform-build) for dependencies. 63 | 64 | Then, 65 | 66 | ```bash 67 | $ yarn package-all 68 | ``` 69 | 70 | To package apps with options: 71 | 72 | ```bash 73 | $ yarn package --[option] 74 | ``` 75 | 76 | To run End-to-End Test 77 | 78 | ```bash 79 | $ yarn build-e2e 80 | $ yarn test-e2e 81 | 82 | # Running e2e tests in a minimized window 83 | $ START_MINIMIZED=true yarn build-e2e 84 | $ yarn test-e2e 85 | ``` 86 | 87 | :bulb: You can debug your production build with devtools by simply setting the `DEBUG_PROD` env variable: 88 | 89 | ```bash 90 | DEBUG_PROD=true yarn package 91 | ``` 92 | 93 | ## CSS Modules 94 | 95 | This boilerplate is configured to use [css-modules](https://github.com/css-modules/css-modules) out of the box. 96 | 97 | All `.css` file extensions will use css-modules unless it has `.global.css`. 98 | 99 | If you need global styles, stylesheets with `.global.css` will not go through the 100 | css-modules loader. e.g. `app.global.css` 101 | 102 | If you want to import global css libraries (like `bootstrap`), you can just write the following code in `.global.css`: 103 | 104 | ```css 105 | @import '~bootstrap/dist/css/bootstrap.css'; 106 | ``` 107 | 108 | ## SASS support 109 | 110 | If you want to use Sass in your app, you only need to import `.sass` files instead of `.css` once: 111 | 112 | ```js 113 | import './app.global.scss'; 114 | ``` 115 | 116 | ## Static Type Checking 117 | 118 | This project comes with Flow support out of the box! You can annotate your code with types, [get Flow errors as ESLint errors](https://github.com/amilajack/eslint-plugin-flowtype-errors), and get [type errors during runtime](https://github.com/codemix/flow-runtime) during development. Types are completely optional. 119 | 120 | ## TODOS 121 | 122 | - Add app icon 123 | - ~~Set up CI for release. (Windows, Mac, Linux)~~ 124 | - Clean up the code base and all the unneeded boilerplate code. 125 | - ~~Create other releases besides Windows.~~ 126 | - Add tests 127 | - Support other types of add use cases besides the assumed `services` pattern. 128 | - Ability to view previous versions 129 | - Logging 130 | - Backup 131 | - Autocomplete (service names) 132 | - ~~Configure AWS Setup (Environments, etc.)~~ 133 | - Bulk delete 134 | - Bulk edit 135 | 136 | and a lot more... 137 | -------------------------------------------------------------------------------- /app/Routes.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Switch, Route } from 'react-router'; 3 | import routes from './constants/routes'; 4 | import App from './containers/App'; 5 | import Home from './components/Home'; 6 | 7 | export default () => ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | -------------------------------------------------------------------------------- /app/app.global.css: -------------------------------------------------------------------------------- 1 | /* 2 | * @NOTE: Prepend a `~` to css file paths that are in your node_modules 3 | * See https://github.com/webpack-contrib/sass-loader#imports 4 | */ 5 | @import '~@fortawesome/fontawesome-free/css/all.css'; 6 | @import '~antd/dist/antd.css'; 7 | 8 | body { 9 | position: relative; 10 | height: 100vh; 11 | font-family: Arial, Helvetica, Helvetica Neue, serif; 12 | overflow-y: hidden; 13 | } 14 | -------------------------------------------------------------------------------- /app/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Parameter Store Manager 6 | 17 | 18 | 19 |
20 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /app/app.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/smblee/parameter-store-manager/7da224be7cd3f8821fdbb58eb32fa64e7cfec2ea/app/app.icns -------------------------------------------------------------------------------- /app/clients/aws.js: -------------------------------------------------------------------------------- 1 | import AWS from 'aws-sdk'; 2 | import localStore from '../store/localStore'; 3 | 4 | process.env.AWS_SDK_LOAD_CONFIG = true; 5 | 6 | const credentialProvider = new AWS.CredentialProviderChain([ 7 | () => new AWS.EnvironmentCredentials('AWS'), 8 | () => new AWS.EnvironmentCredentials('AMAZON'), 9 | () => 10 | new AWS.SharedIniFileCredentials({ profile: localStore.get('profile') }), 11 | () => new AWS.ProcessCredentials({ profile: localStore.get('profile') }) 12 | // TODO: Add more credential providers as needed. https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/CredentialProviderChain.html#providers-property 13 | ]); 14 | 15 | const ssm = region => 16 | new AWS.SSM({ region, credentials: null, credentialProvider }); 17 | const kms = region => 18 | new AWS.KMS({ region, credentials: null, credentialProvider }); 19 | 20 | const getSSM = () => ssm(localStore.get('ssmRegion')); 21 | const getKMS = () => kms(localStore.get('kmsRegion')); 22 | 23 | export default { 24 | getSSM, 25 | getKMS 26 | }; 27 | -------------------------------------------------------------------------------- /app/components/CreationForm.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import { 4 | Button, 5 | Checkbox, 6 | Col, 7 | Form, 8 | Input, 9 | notification, 10 | Radio, 11 | Row, 12 | Select 13 | } from 'antd'; 14 | 15 | import { bindActionCreators } from 'redux'; 16 | import { connect } from 'react-redux'; 17 | import { formShape, formDataShape } from './formDataShape.propType'; 18 | import { 19 | actions as parameterActions, 20 | selectors as parameterSelectors 21 | } from '../ducks/parameters'; 22 | 23 | const { Option } = Select; 24 | const { TextArea } = Input; 25 | 26 | const ENTITY_STATUS = { 27 | initial: 'entity_status:initial', 28 | loading: 'entity_status:loading', 29 | loaded: 'entity_status:loaded', 30 | error: 'entity_status:error' 31 | }; 32 | 33 | class CreationForm extends React.Component { 34 | static propTypes = { 35 | createGenericParameter: PropTypes.func.isRequired, 36 | createServiceParameters: PropTypes.func.isRequired, 37 | editFlow: PropTypes.bool.isRequired, 38 | fetchKmsKeys: PropTypes.func.isRequired, 39 | form: PropTypes.shape(formShape).isRequired, 40 | initialFormData: PropTypes.shape(formDataShape), 41 | kmsKeyLoadError: PropTypes.bool, 42 | kmsKeyLoaded: PropTypes.bool, 43 | kmsKeyLoading: PropTypes.bool, 44 | kmsKeys: PropTypes.arrayOf(PropTypes.object) 45 | }; 46 | 47 | static defaultProps = { 48 | initialFormData: null, 49 | kmsKeyLoadError: false, 50 | kmsKeyLoaded: false, 51 | kmsKeyLoading: false, 52 | kmsKeys: [] 53 | }; 54 | 55 | constructor(props) { 56 | super(props); 57 | 58 | const { initialFormData, editFlow } = props; 59 | 60 | this.state = { 61 | creationType: initialFormData || editFlow ? 'generic' : 'service', 62 | creationState: ENTITY_STATUS.initial, 63 | initialFormData: initialFormData || {} 64 | }; 65 | } 66 | 67 | componentDidMount() { 68 | const { fetchKmsKeys } = this.props; 69 | fetchKmsKeys(); 70 | } 71 | 72 | handleSubmit = e => { 73 | e.preventDefault(); 74 | const { 75 | form, 76 | editFlow, 77 | createServiceParameters, 78 | createGenericParameter 79 | } = this.props; 80 | const { validateFields } = form; 81 | validateFields((validationErr, values) => { 82 | if (!validationErr) { 83 | const { creationType } = this.state; 84 | const creationFn = 85 | creationType === 'service' 86 | ? createServiceParameters 87 | : createGenericParameter; 88 | this.setState({ creationState: ENTITY_STATUS.loading }); 89 | creationFn(values, !!editFlow) 90 | .then(res => { 91 | notification.success({ 92 | message: editFlow 93 | ? 'Parameter was saved.' 94 | : 'Parameter(s) were created.' 95 | }); 96 | this.setState({ creationState: ENTITY_STATUS.loaded }); 97 | return res; 98 | }) 99 | .catch(creationError => { 100 | notification.error({ 101 | message: editFlow 102 | ? 'Parameter was not saved' 103 | : 'One or more parameters were not created.', 104 | description: creationError.message || '' 105 | }); 106 | this.setState({ creationState: ENTITY_STATUS.error }); 107 | }); 108 | } 109 | }); 110 | }; 111 | 112 | onCreationTypeChange = e => { 113 | this.setState({ creationType: e.target.value }); 114 | }; 115 | 116 | render() { 117 | const { 118 | form, 119 | kmsKeyLoading, 120 | kmsKeyLoaded, 121 | kmsKeyLoadError, 122 | kmsKeys, 123 | editFlow 124 | } = this.props; 125 | 126 | const { getFieldDecorator } = form; 127 | const { creationType, creationState, initialFormData } = this.state; 128 | const formItemLayout = { 129 | labelCol: { span: 6 }, 130 | wrapperCol: { span: 14 } 131 | }; 132 | 133 | return ( 134 |
135 | {!editFlow && ( 136 |
143 | Parameter Type: 144 | 149 | Service 150 | Generic 151 | 152 | Client 153 | 154 | 155 |
156 | )} 157 |
158 | {creationType === 'service' && ( 159 | 160 | {getFieldDecorator('serviceName', { 161 | rules: [ 162 | { 163 | required: true, 164 | message: "Please provide the service's name." 165 | }, 166 | { 167 | pattern: /^[^\s\\/]+$/, 168 | message: 'Whitespace, /, \\ is not allowed.' 169 | } 170 | ] 171 | })()} 172 | 173 | )} 174 | 175 | {getFieldDecorator('name', { 176 | initialValue: initialFormData.name, 177 | rules: [ 178 | { 179 | required: true, 180 | message: 'Please provide the parameter name.' 181 | }, 182 | creationType === 'service' && { 183 | pattern: /^[^\s\\/]+$/, 184 | message: 'Whitespace, /, \\ is not allowed.' 185 | } 186 | ] 187 | })( 188 | 196 | )} 197 | 198 | 199 | 200 | {getFieldDecorator('description', { 201 | initialValue: initialFormData.description 202 | })( 203 | 204 | )} 205 | 206 | {creationType === 'service' && ( 207 | 208 | {getFieldDecorator('environments', { 209 | initialValue: ['local', 'fea', 'stg', 'prd'], 210 | rules: [ 211 | { 212 | required: true, 213 | message: 'Please select at least one environment', 214 | type: 'array' 215 | } 216 | ] 217 | })( 218 | 219 | 220 | 221 | local 222 | 223 | 224 | fea 225 | 226 | 227 | stg 228 | 229 | 230 | prd 231 | 232 | 233 | common 234 | 235 | 236 | 237 | )} 238 | 239 | )} 240 | 241 | {getFieldDecorator('type', { 242 | initialValue: initialFormData.type || 'String', 243 | rules: [ 244 | { required: true, message: 'Please select the parameter type.' } 245 | ] 246 | })( 247 | 248 | String 249 | SecureString 250 | 251 | StringList (Not supported yet) 252 | 253 | 254 | )} 255 | 256 | {form.getFieldValue('type') === 'SecureString' && ( 257 | 258 | {getFieldDecorator('kmsKey', { 259 | initialValue: initialFormData.kmsKey, 260 | rules: [ 261 | { 262 | required: true, 263 | message: 264 | 'Please select the KMS Key to encrypt the Secure String.' 265 | } 266 | ] 267 | })( 268 | 285 | )} 286 | 287 | )} 288 | 289 | {getFieldDecorator('value', { 290 | initialValue: initialFormData.value, 291 | rules: [ 292 | { required: true, message: 'Please provide the value.' }, 293 | { 294 | max: 4096, 295 | message: 'The maximum allowed length is 4096 characters.' 296 | } 297 | ] 298 | })(