├── docs ├── images │ ├── logs.png │ ├── Secrets-Proxy.png │ └── keywhiz-proxy-arch.png ├── apidocs │ ├── swagger-ui.css.map │ ├── favicon-16x16.png │ ├── favicon-32x32.png │ ├── swagger-ui.js.map │ ├── swagger-ui-standalone-preset.js.map │ ├── swagger-ui-bundle.js.map │ └── oauth2-redirect.html └── javadocs │ ├── package-list │ ├── script.js │ ├── com │ └── oneops │ │ ├── proxy │ │ ├── package-frame.html │ │ ├── ldap │ │ │ └── package-frame.html │ │ ├── service │ │ │ └── package-frame.html │ │ ├── swagger │ │ │ └── package-frame.html │ │ ├── services │ │ │ └── package-frame.html │ │ ├── exception │ │ │ └── package-frame.html │ │ ├── web │ │ │ ├── support │ │ │ │ └── package-frame.html │ │ │ └── package-frame.html │ │ ├── authz │ │ │ └── package-frame.html │ │ ├── gateway │ │ │ └── package-frame.html │ │ ├── metrics │ │ │ └── package-frame.html │ │ ├── endpoint │ │ │ └── package-frame.html │ │ ├── keywhiz │ │ │ ├── package-frame.html │ │ │ └── http │ │ │ │ └── package-frame.html │ │ ├── security │ │ │ ├── annotations │ │ │ │ └── package-frame.html │ │ │ └── package-frame.html │ │ ├── auth │ │ │ ├── token │ │ │ │ └── package-frame.html │ │ │ ├── user │ │ │ │ └── package-frame.html │ │ │ └── login │ │ │ │ └── package-frame.html │ │ ├── audit │ │ │ └── package-frame.html │ │ ├── model │ │ │ └── package-frame.html │ │ └── config │ │ │ └── package-frame.html │ │ └── user │ │ ├── package-frame.html │ │ └── tables │ │ ├── package-frame.html │ │ └── records │ │ └── package-frame.html │ └── index.html ├── src ├── main │ ├── resources │ │ ├── keystores │ │ │ ├── keywhiz_keystore.p12 │ │ │ ├── ldap_truststore.p12 │ │ │ ├── keywhiz_truststore.p12 │ │ │ └── keywhiz_proxy_keystore.p12 │ │ ├── static │ │ │ └── favicon.ico │ │ ├── banner.txt │ │ ├── META-INF │ │ │ └── additional-spring-configuration-metadata.json │ │ ├── logback-access.xml │ │ └── logback-spring.xml │ └── java │ │ └── com │ │ └── oneops │ │ └── proxy │ │ ├── keywhiz │ │ ├── model │ │ │ ├── v2 │ │ │ │ ├── ModifyClientRequestV2.java │ │ │ │ ├── SecretContentsRequestV2.java │ │ │ │ ├── ModifyGroupsRequestV2.java │ │ │ │ ├── SetSecretVersionRequestV2.java │ │ │ │ ├── SecretContentsResponseV2.java │ │ │ │ ├── CreateGroupRequestV2.java │ │ │ │ ├── CreateClientRequestV2.java │ │ │ │ ├── ClientDetailResponseV2.java │ │ │ │ └── CreateOrUpdateSecretRequestV2.java │ │ │ ├── SecretSeriesAndContent.java │ │ │ ├── CreateClientRequest.java │ │ │ ├── LoginRequest.java │ │ │ ├── AutomationClient.java │ │ │ ├── SecretsResponse.java │ │ │ ├── CreateGroupRequest.java │ │ │ ├── CreateSecretRequest.java │ │ │ ├── AutomationSecretResponse.java │ │ │ ├── SecretSeries.java │ │ │ ├── SecretContent.java │ │ │ ├── ClientDetailResponse.java │ │ │ ├── ApiDate.java │ │ │ └── SanitizedSecretWithGroups.java │ │ ├── KeywhizException.java │ │ └── http │ │ │ └── XsrfTokenInterceptor.java │ │ ├── audit │ │ ├── EventTag.java │ │ ├── AuditLog.java │ │ ├── AuditLogger.java │ │ └── Event.java │ │ ├── authz │ │ └── AuthDomain.java │ │ ├── exception │ │ └── ExitException.java │ │ ├── metrics │ │ ├── ThrowingSupplier.java │ │ └── MetricsUtilService.java │ │ ├── auth │ │ ├── token │ │ │ ├── JwtAuthToken.java │ │ │ └── SkipPathRequestMatcher.java │ │ ├── login │ │ │ ├── LoginFailureHandler.java │ │ │ └── LoginAuthToken.java │ │ └── user │ │ │ ├── LdapUserDetailsService.java │ │ │ └── OneOpsUser.java │ │ ├── Application.java │ │ ├── model │ │ ├── RootResponse.java │ │ ├── SecretVersionRequest.java │ │ ├── SecretContent.java │ │ ├── LoginResponse.java │ │ ├── UserResponse.java │ │ └── LoginRequest.java │ │ ├── security │ │ ├── annotations │ │ │ ├── AuthzRestController.java │ │ │ ├── CurrentUser.java │ │ │ └── AuthorizeGroup.java │ │ ├── RestAuthEntryPoint.java │ │ ├── CliVersionFilter.java │ │ └── GlobalSecurityConfig.java │ │ ├── endpoint │ │ ├── KeywhizHealthIndicator.java │ │ ├── KeywhizEndPoint.java │ │ └── ListEndPoints.java │ │ ├── config │ │ ├── PropertyVerifier.java │ │ ├── MgmtConfig.java │ │ ├── Constants.java │ │ ├── CacheConfig.java │ │ ├── AccessLogFilter.java │ │ └── WebConfig.java │ │ └── web │ │ ├── RootController.java │ │ └── support │ │ ├── AppGroupArgResolver.java │ │ └── AppSecretArgResolver.java ├── generated │ └── java │ │ └── com │ │ └── oneops │ │ └── user │ │ ├── DefaultCatalog.java │ │ ├── tables │ │ ├── SchemaMigrations.java │ │ └── records │ │ │ └── SchemaMigrationsRecord.java │ │ └── Tables.java └── test │ └── java │ └── com │ └── oneops │ └── proxy │ ├── ApplicationTests.java │ └── model │ └── AppSecretTest.java ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .looper.yml ├── contrib ├── README.md ├── scripts │ └── upload-secrets.sh └── init │ └── systemd │ ├── keywhiz-proxy.service │ ├── keywhiz-proxy-env │ └── README.md ├── .github ├── ISSUE_TEMPLATE.md ├── PULL_REQUEST_TEMPLATE.md ├── workflows │ └── maven.yml └── CONTRIBUTING.md ├── .gitignore ├── Dockerfile └── CHANGELOG.md /docs/images/logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/docs/images/logs.png -------------------------------------------------------------------------------- /src/main/resources/keystores/keywhiz_keystore.p12: -------------------------------------------------------------------------------- 1 | Keywhiz Keystore Placeholder! Use a proper one. -------------------------------------------------------------------------------- /src/main/resources/keystores/ldap_truststore.p12: -------------------------------------------------------------------------------- 1 | LDAP truststore Placeholder! Use a proper one. -------------------------------------------------------------------------------- /src/main/resources/keystores/keywhiz_truststore.p12: -------------------------------------------------------------------------------- 1 | Keywhiz Truststore Placeholder! Use a proper one. -------------------------------------------------------------------------------- /docs/apidocs/swagger-ui.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.css","sources":[],"mappings":"","sourceRoot":""} -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /docs/apidocs/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/docs/apidocs/favicon-16x16.png -------------------------------------------------------------------------------- /docs/apidocs/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/docs/apidocs/favicon-32x32.png -------------------------------------------------------------------------------- /docs/images/Secrets-Proxy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/docs/images/Secrets-Proxy.png -------------------------------------------------------------------------------- /docs/images/keywhiz-proxy-arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/docs/images/keywhiz-proxy-arch.png -------------------------------------------------------------------------------- /src/main/resources/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/src/main/resources/static/favicon.ico -------------------------------------------------------------------------------- /.looper.yml: -------------------------------------------------------------------------------- 1 | tools: 2 | jdk: 8 3 | maven: 3.5.0 4 | flows: 5 | default: 6 | - shell: mvn clean install 7 | pr: 8 | call: default -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.3/apache-maven-3.5.3-bin.zip -------------------------------------------------------------------------------- /docs/apidocs/swagger-ui.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui.js","sources":["webpack:///swagger-ui.js"],"mappings":"AAAA;;;;;;AA8idA","sourceRoot":""} -------------------------------------------------------------------------------- /contrib/README.md: -------------------------------------------------------------------------------- 1 | The [contrib](https://goo.gl/DUHNBH) directory contains scripts and other helpful things which are not part of the core application jar. -------------------------------------------------------------------------------- /src/main/resources/keystores/keywhiz_proxy_keystore.p12: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/oneops/secrets-proxy/HEAD/src/main/resources/keystores/keywhiz_proxy_keystore.p12 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Expected behavior 2 | 3 | Write here. 4 | 5 | ### Actual behavior 6 | 7 | Write here. 8 | 9 | ### Steps to reproduce behavior 10 | 11 | Write here. -------------------------------------------------------------------------------- /docs/apidocs/swagger-ui-standalone-preset.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-standalone-preset.js","sources":["webpack:///swagger-ui-standalone-preset.js"],"mappings":"AAAA;;;;;AA21CA;;;;;;AAypFA","sourceRoot":""} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | .DS_Store 4 | 5 | ### IntelliJ IDEA ### 6 | .idea 7 | *.iws 8 | *.iml 9 | *.ipr 10 | 11 | ### Ignore the Keystores 12 | src/main/resources/keystores/* 13 | log/ 14 | javadocs/ -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | Write here 4 | 5 | ### Fixes 6 | 7 | Changes proposed in this pull request. 8 | 9 | ### Check List 10 | 11 | - [ ] All test passed 12 | - [ ] Added test to ensure to fix/ensure properly. -------------------------------------------------------------------------------- /docs/apidocs/swagger-ui-bundle.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"swagger-ui-bundle.js","sources":["webpack:///swagger-ui-bundle.js"],"mappings":"AAAA;;;;;AAoyKA;;;;;;AAm/EA;;;;;;;;;;;;;;;;;;;;;;;;;;AAy7TA;;;;;;;;;;;;;;AAs8JA;;;;;;;;;AA2hpBA;;;;;AA41QA;AAm4DA;;;;;;AAo4YA;;;;;;AA8jaA;AAumvBA","sourceRoot":""} -------------------------------------------------------------------------------- /src/main/resources/banner.txt: -------------------------------------------------------------------------------- 1 | ${AnsiColor.CYAN}${AnsiStyle.BOLD} 2 | ____ ____ 3 | / __ \___ ___ / __ \___ ___ 4 | / /_/ / _ \/ -_) /_/ / _ \(_-< 5 | \____/_//_/\__/\____/ .__/___/ 6 | /_/ 7 | ${AnsiStyle.NORMAL} ${application.title}: ${AnsiColor.GREEN} ${AnsiStyle.BOLD}v${application.version} ${AnsiStyle.NORMAL} 8 | 9 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre-alpine as build 2 | ARG VERSION 3 | ADD . /app 4 | RUN cd /app \ 5 | && ./mvnw clean package 6 | 7 | FROM openjdk:8-jre-alpine 8 | VOLUME /secrets /log 9 | COPY --from=build /app/target/secrets-proxy-*.jar app.jar 10 | EXPOSE 8443 11 | ENV JAVA_OPTS="-server -XX:+UseG1GC" 12 | ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ] -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/ModifyClientRequestV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.google.auto.value.AutoValue; 5 | 6 | @AutoValue 7 | public abstract class ModifyClientRequestV2 { 8 | @JsonCreator 9 | public static ModifyClientRequestV2 forName(@JsonProperty("name") String name) { 10 | return new AutoValue_ModifyClientRequestV2(name); 11 | } 12 | 13 | @JsonProperty("name") 14 | public abstract String name(); 15 | } 16 | -------------------------------------------------------------------------------- /.github/workflows/maven.yml: -------------------------------------------------------------------------------- 1 | name: Maven Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ubuntu-latest 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up JDK 8 17 | uses: actions/setup-java@v3 18 | with: 19 | java-version: '8' 20 | distribution: 'temurin' 21 | cache: maven 22 | 23 | - name: Build with Maven 24 | run: ./mvnw -B clean package 25 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/audit/EventTag.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.audit; 2 | 3 | /** 4 | * Possible types of events in Keywhiz Proxy. 5 | * 6 | * @author Suresh G 7 | */ 8 | public enum EventTag { 9 | SECRET_CREATE, 10 | SECRET_CREATEORUPDATE, 11 | SECRET_UPDATE, 12 | SECRET_CHANGEVERSION, 13 | SECRET_DELETE, 14 | SECRET_BACKFILLEXPIRY, 15 | SECRET_READCONTENT, 16 | 17 | GROUP_CREATE, 18 | GROUP_DELETE, 19 | GROUP_BACKUP, 20 | 21 | CLIENT_CREATE, 22 | CLIENT_DELETE, 23 | 24 | CHANGEACL_GROUP_SECRET, 25 | CHANGEACL_GROUP_CLIENT, 26 | 27 | GENERATE_TOKEN 28 | } 29 | -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to OneOps 2 | 3 | ## Contributor License Agreement ("CLA") 4 | 5 | In order to accept your pull request, we need you to submit a CLA. You only need to do this once, so if you've done this for another Walmart open source project, you're good to go. If you are submitting a pull request for the first time, just let us know that you have completed the CLA and we can cross-check with your GitHub username. 6 | 7 | More details to complete your CLA can be found at . 8 | 9 | ## License 10 | 11 | By contributing to OneOps, you agree that your contributions will be licensed under the [Apache License Version 2.0 (APLv2)](LICENSE). -------------------------------------------------------------------------------- /docs/javadocs/package-list: -------------------------------------------------------------------------------- 1 | com.oneops.proxy 2 | com.oneops.proxy.audit 3 | com.oneops.proxy.auth.login 4 | com.oneops.proxy.auth.token 5 | com.oneops.proxy.auth.user 6 | com.oneops.proxy.authz 7 | com.oneops.proxy.config 8 | com.oneops.proxy.endpoint 9 | com.oneops.proxy.exception 10 | com.oneops.proxy.gateway 11 | com.oneops.proxy.keywhiz 12 | com.oneops.proxy.keywhiz.http 13 | com.oneops.proxy.keywhiz.model 14 | com.oneops.proxy.keywhiz.model.v2 15 | com.oneops.proxy.ldap 16 | com.oneops.proxy.metrics 17 | com.oneops.proxy.model 18 | com.oneops.proxy.security 19 | com.oneops.proxy.security.annotations 20 | com.oneops.proxy.service 21 | com.oneops.proxy.swagger 22 | com.oneops.proxy.web 23 | com.oneops.proxy.web.support 24 | com.oneops.user 25 | com.oneops.user.tables 26 | com.oneops.user.tables.records 27 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/authz/AuthDomain.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.authz; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | 6 | /** 7 | * OneOps auth domains. The user data source for each corresponding domain is configured in the 8 | * application.yaml. 9 | * 10 | * @author Suresh 11 | */ 12 | public enum AuthDomain { 13 | 14 | /*Oneops domain name*/ 15 | PROD("prod"), 16 | MGMT("mgmt"), 17 | STG("stg"), 18 | DEV("dev"); 19 | 20 | private final String type; 21 | 22 | AuthDomain(String type) { 23 | this.type = type; 24 | } 25 | 26 | /** This is for dealing with case insensitive enum in json. */ 27 | @JsonCreator 28 | public static AuthDomain of(String type) { 29 | return AuthDomain.valueOf(type.toUpperCase()); 30 | } 31 | 32 | @JsonValue 33 | public String getType() { 34 | return type; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /docs/javadocs/script.js: -------------------------------------------------------------------------------- 1 | function show(type) 2 | { 3 | count = 0; 4 | for (var key in methods) { 5 | var row = document.getElementById(key); 6 | if ((methods[key] & type) != 0) { 7 | row.style.display = ''; 8 | row.className = (count++ % 2) ? rowColor : altColor; 9 | } 10 | else 11 | row.style.display = 'none'; 12 | } 13 | updateTabs(type); 14 | } 15 | 16 | function updateTabs(type) 17 | { 18 | for (var value in tabs) { 19 | var sNode = document.getElementById(tabs[value][0]); 20 | var spanNode = sNode.firstChild; 21 | if (value == type) { 22 | sNode.className = activeTableTab; 23 | spanNode.innerHTML = tabs[value][1]; 24 | } 25 | else { 26 | sNode.className = tableTab; 27 | spanNode.innerHTML = "" + tabs[value][1] + ""; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy

14 |
15 |

Classes

16 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/ldap/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.ldap (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.ldap

14 |
15 |

Classes

16 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/service/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.service (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.service

14 |
15 |

Classes

16 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/swagger/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.swagger (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.swagger

14 |
15 |

Classes

16 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/services/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.service (OneOps Keywhiz Proxy 1.0.0 API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.service

14 |
15 |

Classes

16 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/exception/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.exception (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.exception

14 |
15 |

Exceptions

16 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/audit/AuditLog.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.audit; 19 | 20 | /** 21 | * Audit logger interface for recording events. 22 | * 23 | * @author Suresh G 24 | */ 25 | public interface AuditLog { 26 | 27 | /** 28 | * Record an event ${@link EventTag} 29 | * 30 | * @param e {@link Event} 31 | */ 32 | void log(Event e); 33 | } 34 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/web/support/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.web.support (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.web.support

14 |
15 |

Classes

16 | 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/SecretSeriesAndContent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import com.google.auto.value.AutoValue; 20 | 21 | /** Value type containing a secret content and associated series. */ 22 | @AutoValue 23 | public abstract class SecretSeriesAndContent { 24 | 25 | public static SecretSeriesAndContent of(SecretSeries series, SecretContent content) { 26 | return new AutoValue_SecretSeriesAndContent(series, content); 27 | } 28 | 29 | public abstract SecretSeries series(); 30 | 31 | public abstract SecretContent content(); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/exception/ExitException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.exception; 19 | 20 | import org.springframework.boot.ExitCodeGenerator; 21 | 22 | /** 23 | * Defines an exit exception with proper error code. 24 | * 25 | * @author Suresh G 26 | */ 27 | public class ExitException extends RuntimeException implements ExitCodeGenerator { 28 | @Override 29 | public int getExitCode() { 30 | return 1; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/authz/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.authz (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.authz

14 |
15 |

Classes

16 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/gateway/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.gateway (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.gateway

14 |
15 |

Classes

16 | 19 |

Enums

20 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /src/generated/java/com/oneops/user/DefaultCatalog.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package com.oneops.user; 5 | 6 | import org.jooq.Schema; 7 | import org.jooq.impl.CatalogImpl; 8 | 9 | import javax.annotation.Generated; 10 | import java.util.*; 11 | 12 | /** This class is generated by jOOQ. */ 13 | @Generated( 14 | value = {"http://www.jooq.org", "jOOQ version:3.9.2"}, 15 | comments = "This class is generated by jOOQ" 16 | ) 17 | @SuppressWarnings({"all", "unchecked", "rawtypes"}) 18 | public class DefaultCatalog extends CatalogImpl { 19 | 20 | private static final long serialVersionUID = -1612708647; 21 | 22 | /** The reference instance of */ 23 | public static final DefaultCatalog DEFAULT_CATALOG = new DefaultCatalog(); 24 | 25 | /** The schema public. */ 26 | public final Public PUBLIC = com.oneops.user.Public.PUBLIC; 27 | 28 | /** No further instances allowed */ 29 | private DefaultCatalog() { 30 | super(""); 31 | } 32 | 33 | @Override 34 | public final List getSchemas() { 35 | List result = new ArrayList(); 36 | result.addAll(getSchemas0()); 37 | return result; 38 | } 39 | 40 | private final List getSchemas0() { 41 | return Arrays.asList(Public.PUBLIC); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/metrics/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.metrics (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.metrics

14 |
15 |

Interfaces

16 | 19 |

Classes

20 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/audit/AuditLogger.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.audit; 19 | 20 | import org.slf4j.*; 21 | import org.springframework.stereotype.Component; 22 | 23 | /** 24 | * Audit logger for logging events. 25 | * 26 | * @author Suresh 27 | */ 28 | @Component 29 | public class AuditLogger implements AuditLog { 30 | 31 | private final Logger log = LoggerFactory.getLogger(AuditLog.class); 32 | 33 | @Override 34 | public void log(Event e) { 35 | log.info(e.toString()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/endpoint/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.endpoint (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.endpoint

14 |
15 |

Classes

16 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /src/test/java/com/oneops/proxy/ApplicationTests.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy; 19 | 20 | import org.junit.Test; 21 | import org.junit.runner.RunWith; 22 | import org.springframework.boot.test.context.SpringBootTest; 23 | import org.springframework.test.context.junit4.SpringRunner; 24 | 25 | /** 26 | * Main application tests 27 | * 28 | * @author Suresh G 29 | */ 30 | @RunWith(SpringRunner.class) 31 | @SpringBootTest 32 | public class ApplicationTests { 33 | 34 | @Test 35 | public void contextLoads() {} 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/SecretContentsRequestV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.google.auto.value.AutoValue; 5 | import com.google.common.collect.ImmutableSet; 6 | 7 | @AutoValue 8 | public abstract class SecretContentsRequestV2 { 9 | SecretContentsRequestV2() {} // prevent sub-classing 10 | 11 | public static Builder builder() { 12 | return new AutoValue_SecretContentsRequestV2.Builder().secrets(); 13 | } 14 | 15 | @AutoValue.Builder 16 | public abstract static class Builder { 17 | // intended to be package-private 18 | abstract SecretContentsRequestV2.Builder secrets(ImmutableSet secrets); 19 | 20 | public SecretContentsRequestV2.Builder secrets(String... secrets) { 21 | return secrets(ImmutableSet.copyOf(secrets)); 22 | } 23 | 24 | public abstract SecretContentsRequestV2 build(); 25 | } 26 | 27 | /** Static factory method used by Jackson for deserialization */ 28 | @SuppressWarnings("unused") 29 | @JsonCreator 30 | public static SecretContentsRequestV2 fromParts( 31 | @JsonProperty("secrets") ImmutableSet secrets) { 32 | return builder().secrets(secrets).build(); 33 | } 34 | 35 | @JsonProperty("secrets") 36 | public abstract ImmutableSet secrets(); 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/metrics/ThrowingSupplier.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.metrics; 19 | 20 | /** 21 | * A throwing supplier. Useful in lambda expressions/streams. 22 | * 23 | * @param the type of results supplied by this supplier 24 | * @param the type of checked exception thrown by this supplier. 25 | */ 26 | @FunctionalInterface 27 | public interface ThrowingSupplier { 28 | 29 | /** 30 | * Gets a result. 31 | * 32 | * @return a result 33 | */ 34 | T get() throws E; 35 | } 36 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/additional-spring-configuration-metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "properties": [ 3 | { 4 | "name": "logging.audit-file", 5 | "type": "java.lang.String", 6 | "description": "Audit log file name." 7 | }, 8 | { 9 | "name": "jetty.thread-pool.min-threads", 10 | "type": "java.lang.String", 11 | "description": "Jetty thread pool min threads." 12 | }, 13 | { 14 | "name": "jetty.thread-pool.max-threads", 15 | "type": "java.lang.String", 16 | "description": "Jetty thread pool min threads." 17 | }, 18 | { 19 | "name": "jetty.thread-pool.idle-timeout", 20 | "type": "java.lang.String", 21 | "description": "Jetty thread pool idle-timeout." 22 | }, 23 | { 24 | "name": "logback.access.file", 25 | "type": "java.lang.String", 26 | "description": "Jetty access log file name." 27 | }, 28 | { 29 | "name": "jetty.jmx.enabled", 30 | "type": "java.lang.String", 31 | "description": "Jetty jmx enabled." 32 | }, 33 | { 34 | "name": "management.user", 35 | "type": "java.lang.String", 36 | "description": "Management custom user name." 37 | }, 38 | { 39 | "name": "management.password", 40 | "type": "java.lang.String", 41 | "description": "Management custom password." 42 | } 43 | ] 44 | } -------------------------------------------------------------------------------- /src/test/java/com/oneops/proxy/model/AppSecretTest.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.model; 2 | 3 | import static org.junit.Assert.assertEquals; 4 | 5 | import com.oneops.proxy.authz.AuthDomain; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import org.junit.Test; 9 | 10 | /** 11 | * Test app secrets. 12 | * 13 | * @author Suresh 14 | */ 15 | public class AppSecretTest { 16 | 17 | @Test 18 | public void getUniqSecretName() throws Exception { 19 | 20 | AppGroup appGroup1 = new AppGroup(AuthDomain.PROD, "oneops_my-app1_prod"); 21 | AppGroup appGroup2 = new AppGroup(AuthDomain.MGMT, "oneops_my-app2_prod"); 22 | 23 | System.out.println(appGroup1); 24 | System.out.println(appGroup2); 25 | List secretNames = 26 | Arrays.asList("db-password.txt", "db@password.txt", "db:password.txt", "db_password.txt"); 27 | secretNames.forEach( 28 | secret -> { 29 | AppSecret secret1 = new AppSecret(secret, appGroup1); 30 | AppSecret secret2 = new AppSecret(secret, appGroup2); 31 | 32 | assertEquals(secret, secret1.getSecretName()); 33 | assertEquals(secret, secret2.getSecretName()); 34 | 35 | assertEquals(secret, new AppSecret(secret1.getUniqSecretName()).getSecretName()); 36 | assertEquals(secret, new AppSecret(secret2.getUniqSecretName()).getSecretName()); 37 | }); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/user/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.user (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.user

14 |
15 |

Classes

16 | 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/keywhiz/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.keywhiz (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.keywhiz

14 |
15 |

Classes

16 | 20 |

Exceptions

21 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /contrib/scripts/upload-secrets.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This script is used for uploading secrets of 4 | # the Keywhiz Proxy environment itself. 5 | 6 | set -e 7 | 8 | if [ -z ${SECRETS_TOKEN} ]; then 9 | echo "SECRETS_TOKEN not set!" 10 | exit 1; 11 | fi 12 | 13 | # Secrets files 14 | secrets_dir=/keywhiz-proxy/secrets/ 15 | secrets=( 16 | 'keywhiz-proxy-env::Secrets Proxy Application Env Config.' 17 | 'keystores/keywhiz_keystore.p12::Keywhiz Automation mTLS Client Certificate.' 18 | 'keystores/keywhiz_proxy_keystore.p12::TLS Server Certificate For Secrets Proxy Application.' 19 | 'keystores/keywhiz_truststore.p12::Keywhiz Server Trust-Store.' 20 | 'keystores/ldap_truststore.p12::LDAP/AD Server Trust-Store.' 21 | ) 22 | 23 | cd ${secrets_dir} 24 | for index in "${secrets[@]}" ; do 25 | secret="${index%%::*}" 26 | desc="${index##*::}" 27 | name=${secret##*/} 28 | 29 | echo -e "\n\xF0\x9F\x8D\xBB Uploading secret \033[36m$secret\033[0m with name: \033[36m$name\033[0m , desc: $desc" 30 | base64_content=$(base64 -in ${secret}) 31 | payload="{\"description\":\"${desc}\",\"content\":\"${base64_content}\"}" 32 | 33 | curl -k -X POST -H "Content-Type: application/json" -H "X-Authorization: Bearer ${SECRETS_TOKEN}" https://localhost:8443/v1/apps/oneops_keywhiz-proxy_prod/secrets/${name} -d"$payload" 34 | echo -e "\n\xE2\x9C\x94 - Uploaded \033[36m$secret\033[0m." 35 | done 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/security/annotations/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.security.annotations (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.security.annotations

14 |
15 |

Annotation Types

16 | 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/auth/token/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.auth.token (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.auth.token

14 |
15 |

Classes

16 | 22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/CreateClientRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.common.base.Objects; 21 | 22 | public class CreateClientRequest { 23 | 24 | @JsonProperty public String name; 25 | 26 | public CreateClientRequest(@JsonProperty("name") String name) { 27 | this.name = name; 28 | } 29 | 30 | @Override 31 | public int hashCode() { 32 | return Objects.hashCode(name); 33 | } 34 | 35 | @Override 36 | public boolean equals(Object o) { 37 | if (this == o) return true; 38 | if (o instanceof CreateClientRequest) { 39 | CreateClientRequest that = (CreateClientRequest) o; 40 | if (Objects.equal(this.name, that.name)) { 41 | return true; 42 | } 43 | } 44 | return false; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/auth/token/JwtAuthToken.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.auth.token; 19 | 20 | import java.util.Collection; 21 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; 22 | import org.springframework.security.core.GrantedAuthority; 23 | 24 | /** 25 | * A token for identifying JWT auth token in {@link TokenAuthProcessingFilter}. 26 | * 27 | * @author Suresh 28 | */ 29 | public class JwtAuthToken extends UsernamePasswordAuthenticationToken { 30 | 31 | public JwtAuthToken( 32 | Object principal, Object credentials, Collection authorities) { 33 | super(principal, credentials, authorities); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/auth/user/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.auth.user (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.auth.user

14 |
15 |

Classes

16 | 21 |

Enums

22 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/Application.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy; 19 | 20 | import com.oneops.proxy.config.OneOpsConfig; 21 | import org.springframework.boot.SpringApplication; 22 | import org.springframework.boot.autoconfigure.SpringBootApplication; 23 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 24 | 25 | /** 26 | * Keywhiz proxy application. 27 | * 28 | * @author Suresh 29 | */ 30 | @SpringBootApplication 31 | @EnableConfigurationProperties(OneOpsConfig.class) 32 | public class Application { 33 | 34 | public static void main(String[] args) { 35 | System.setProperty("org.jooq.no-logo", "true"); 36 | SpringApplication.run(Application.class, args); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/model/RootResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.model; 19 | 20 | /** 21 | * Response for application root request. 22 | * 23 | * @author Suresh 24 | */ 25 | public class RootResponse { 26 | 27 | private final String name; 28 | private final String version; 29 | 30 | public RootResponse(String name, String version) { 31 | this.name = name; 32 | this.version = version; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public String getVersion() { 40 | return version; 41 | } 42 | 43 | @Override 44 | public String toString() { 45 | return "RootResponse{" + "name='" + name + '\'' + ", version='" + version + '\'' + '}'; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/audit/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.audit (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.audit

14 |
15 |

Interfaces

16 | 19 |

Classes

20 | 24 |

Enums

25 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /contrib/init/systemd/keywhiz-proxy.service: -------------------------------------------------------------------------------- 1 | # OneOps Secrets Proxy Service Unit File 2 | # Updated On : 28/Sep/2017 3 | ######################################## 4 | 5 | [Unit] 6 | Description=OneOps Secrets Proxy Service 7 | Documentation=https://oneops.github.com/secrets-proxy/apidocs 8 | After=network.target syslog.target ntpd.service 9 | Wants=ntpd.service 10 | 11 | [Service] 12 | Type=simple 13 | # PIDFile=/var/run/keywhiz-proxy.pid 14 | Environment=SECRETS_CLI_VERSION=$OO_LOCAL{secrets-cli-version} 15 | Environment=SECRETS_CLI_PATH=$OO_LOCAL{secrets-cli-path} 16 | EnvironmentFile=-/secrets/keywhiz-proxy-env 17 | WorkingDirectory=/opt/oneops/keywhiz-proxy/ 18 | ExecStart=/bin/java -server \ 19 | -Xms2000m -Xmx6000m \ 20 | -XX:+UseG1GC -XX:MaxGCPauseMillis=200 -XX:InitiatingHeapOccupancyPercent=70 \ 21 | -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -Xloggc:/log/gclogs/keywhiz-proxy-gc.log \ 22 | -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=15 -XX:GCLogFileSize=10M \ 23 | -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/heap-dump/keywhiz-proxy.hprof \ 24 | -jar /opt/oneops/keywhiz-proxy/$OO_LOCAL{keywhiz-proxy-artifact}-$OO_LOCAL{keywhiz-proxy-version}.jar 25 | ExecReload=/bin/kill -s HUP $MAINPID 26 | SuccessExitStatus=143 27 | KillMode=process 28 | Restart=on-failure 29 | RestartSec=3s 30 | User=root 31 | Group=root 32 | LimitNOFILE=1048576 33 | LimitNPROC=1048576 34 | LimitCORE=infinity 35 | 36 | [Install] 37 | WantedBy=multi-user.target 38 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/keywhiz/http/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.keywhiz.http (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.keywhiz.http

14 |
15 |

Interfaces

16 | 19 |

Classes

20 | 25 |
26 | 27 | 28 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/model/SecretVersionRequest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.model; 19 | 20 | import com.fasterxml.jackson.annotation.JsonProperty; 21 | 22 | /** 23 | * Secret version request for set version. 24 | * 25 | * @author Suresh G 26 | */ 27 | public class SecretVersionRequest { 28 | 29 | @JsonProperty private long version; 30 | 31 | public SecretVersionRequest() {} 32 | 33 | public SecretVersionRequest(long version) { 34 | this.version = version; 35 | } 36 | 37 | public long getVersion() { 38 | return version; 39 | } 40 | 41 | public void setVersion(long version) { 42 | this.version = version; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "SecretVersionRequest{" + "version=" + version + '}'; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/security/annotations/AuthzRestController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.security.annotations; 19 | 20 | import com.oneops.proxy.auth.user.OneOpsUser; 21 | import com.oneops.proxy.authz.Authz; 22 | import java.lang.annotation.*; 23 | import org.springframework.web.bind.annotation.RestController; 24 | 25 | /** 26 | * A meta annotation for {@link RestController} with a pre authorization for Keywhiz application 27 | * group name. All {@link AuthzRestController} methods should have {@link OneOpsUser} as mandatory 28 | * method parameter for Pre Authorization ({@link Authz#isAuthorized(String, OneOpsUser)}). 29 | * 30 | * @author Suresh G 31 | */ 32 | @RestController 33 | @AuthorizeGroup 34 | @Retention(RetentionPolicy.RUNTIME) 35 | public @interface AuthzRestController {} 36 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/auth/login/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.auth.login (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.auth.login

14 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /src/main/resources/logback-access.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | ${LOG_PATH}/access/${LOG_FILE}.log 9 | 10 | 11 | /webjars/.*,/swagger-resources.* 12 | DENY 13 | ACCEPT 14 | 15 | 16 | 17 | %i{NSC-Client-IP} %h %l %u [%t] "%r" %s %b [%D] "%i{Referer}" "%i{User-Agent}" 18 | 19 | 20 | 21 | ${LOG_PATH}/access/${LOG_FILE}-%d{yyyy-MM-dd}.%i.log.zip 22 | 23 | 50MB 24 | 30 25 | 1GB 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/web/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.web (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.web

14 |
15 |

Classes

16 | 24 |
25 | 26 | 27 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/LoginRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import static com.google.common.base.Strings.repeat; 20 | 21 | import com.fasterxml.jackson.annotation.*; 22 | import com.google.auto.value.AutoValue; 23 | import com.google.common.base.MoreObjects; 24 | 25 | @AutoValue 26 | public abstract class LoginRequest { 27 | @JsonCreator 28 | public static LoginRequest from( 29 | @JsonProperty("username") String username, @JsonProperty("password") char[] password) { 30 | return new AutoValue_LoginRequest(username, password); 31 | } 32 | 33 | @JsonProperty 34 | public abstract String username(); 35 | 36 | @SuppressWarnings("mutable") 37 | @JsonProperty 38 | public abstract char[] password(); 39 | 40 | @Override 41 | public String toString() { 42 | return MoreObjects.toStringHelper(this) 43 | .add("username", username()) 44 | .add("password", repeat("*", password().length)) 45 | .toString(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/ModifyGroupsRequestV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.google.auto.value.AutoValue; 5 | import com.google.common.collect.ImmutableSet; 6 | 7 | @AutoValue 8 | public abstract class ModifyGroupsRequestV2 { 9 | ModifyGroupsRequestV2() {} // prevent sub-classing 10 | 11 | public static Builder builder() { 12 | return new AutoValue_ModifyGroupsRequestV2.Builder().addGroups().removeGroups(); 13 | } 14 | 15 | @AutoValue.Builder 16 | public abstract static class Builder { 17 | // intended to be package-private 18 | abstract Builder addGroups(ImmutableSet groups); 19 | 20 | abstract Builder removeGroups(ImmutableSet groups); 21 | 22 | public Builder addGroups(String... groups) { 23 | return addGroups(ImmutableSet.copyOf(groups)); 24 | } 25 | 26 | public Builder removeGroups(String... groups) { 27 | return removeGroups(ImmutableSet.copyOf(groups)); 28 | } 29 | 30 | public abstract ModifyGroupsRequestV2 build(); 31 | } 32 | 33 | /** Static factory method used by Jackson for deserialization */ 34 | @SuppressWarnings("unused") 35 | @JsonCreator 36 | public static ModifyGroupsRequestV2 fromParts( 37 | @JsonProperty("addGroups") ImmutableSet addGroups, 38 | @JsonProperty("removeGroups") ImmutableSet removeGroups) { 39 | return builder().addGroups(addGroups).removeGroups(removeGroups).build(); 40 | } 41 | 42 | @JsonProperty("addGroups") 43 | public abstract ImmutableSet addGroups(); 44 | 45 | @JsonProperty("removeGroups") 46 | public abstract ImmutableSet removeGroups(); 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/AutomationClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | package com.oneops.proxy.keywhiz.model; 17 | 18 | import com.google.common.base.MoreObjects; 19 | import javax.annotation.Nullable; 20 | 21 | /** Special type of {@link Client} with elevated, automation privileges. */ 22 | public class AutomationClient extends Client { 23 | private AutomationClient(Client client) { 24 | super( 25 | client.getId(), 26 | client.getName(), 27 | client.getDescription(), 28 | client.getCreatedAt(), 29 | client.getCreatedBy(), 30 | client.getUpdatedAt(), 31 | client.getUpdatedBy(), 32 | client.getLastSeen(), 33 | client.isEnabled(), 34 | true); 35 | } 36 | 37 | @Nullable 38 | public static AutomationClient of(Client client) { 39 | if (client.isAutomationAllowed()) { 40 | return new AutomationClient(client); 41 | } 42 | 43 | return null; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return MoreObjects.toStringHelper(this).add("name", getName()).toString(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/security/annotations/CurrentUser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.security.annotations; 19 | 20 | import java.lang.annotation.*; 21 | import org.springframework.security.core.annotation.AuthenticationPrincipal; 22 | import org.springframework.security.core.context.SecurityContextHolder; 23 | 24 | /** 25 | * A meta annotation, annotates spring MVC method args with this annotation to indicate you wish to 26 | * specify the argument with the value of current {@link AuthenticationPrincipal} found on {@link 27 | * SecurityContextHolder}. You could instead use {@link AuthenticationPrincipal} directly, but this 28 | * meta annotation is useful to decouple your Rest controller logic from spring security. 29 | * 30 | * @author Suresh 31 | */ 32 | @Target(ElementType.PARAMETER) 33 | @Retention(RetentionPolicy.RUNTIME) 34 | @Documented 35 | @AuthenticationPrincipal 36 | public @interface CurrentUser {} 37 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/SecretsResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import com.google.common.base.*; 20 | import com.google.common.collect.ImmutableList; 21 | 22 | /** Response to a listing of existing secrets */ 23 | public class SecretsResponse { 24 | /** Listing of secrets with related information but without secret content. */ 25 | public final ImmutableList secrets; 26 | 27 | public SecretsResponse(ImmutableList secrets) { 28 | this.secrets = secrets; 29 | } 30 | 31 | @Override 32 | public int hashCode() { 33 | return Objects.hashCode(secrets); 34 | } 35 | 36 | @Override 37 | public boolean equals(Object o) { 38 | if (o instanceof SecretsResponse) { 39 | SecretsResponse that = (SecretsResponse) o; 40 | if (Objects.equal(this.secrets, that.secrets)) { 41 | return true; 42 | } 43 | } 44 | return false; 45 | } 46 | 47 | @Override 48 | public String toString() { 49 | return MoreObjects.toStringHelper(this).add("secrets", secrets).toString(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/endpoint/KeywhizHealthIndicator.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.endpoint; 19 | 20 | import com.oneops.proxy.keywhiz.KeywhizAutomationClient; 21 | import java.io.IOException; 22 | import java.util.Map; 23 | import org.springframework.boot.actuate.health.*; 24 | import org.springframework.stereotype.Component; 25 | 26 | /** 27 | * Add Keywhiz Server status to health (/health). 28 | * 29 | * @author Suresh 30 | */ 31 | @Component 32 | public class KeywhizHealthIndicator extends AbstractHealthIndicator { 33 | 34 | private final KeywhizAutomationClient kwClient; 35 | 36 | public KeywhizHealthIndicator(KeywhizAutomationClient kwClient) { 37 | this.kwClient = kwClient; 38 | } 39 | 40 | @Override 41 | protected void doHealthCheck(Health.Builder builder) throws Exception { 42 | try { 43 | Map status = kwClient.getStatus(); 44 | builder.up().status(status.get("message").toString()); 45 | } catch (IOException ioe) { 46 | builder.down().withException(ioe); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/SetSecretVersionRequestV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.google.auto.value.AutoValue; 5 | import com.google.common.base.MoreObjects; 6 | 7 | @AutoValue 8 | public abstract class SetSecretVersionRequestV2 { 9 | SetSecretVersionRequestV2() {} // prevent sub-classing 10 | 11 | public static Builder builder() { 12 | return new AutoValue_SetSecretVersionRequestV2.Builder().name("").version(0); 13 | } 14 | 15 | @AutoValue.Builder 16 | public abstract static class Builder { 17 | // intended to be package-private 18 | abstract SetSecretVersionRequestV2 autoBuild(); 19 | 20 | public abstract Builder name(String name); 21 | 22 | public abstract Builder version(long version); 23 | 24 | /** @throws IllegalArgumentException if builder data is invalid. */ 25 | public SetSecretVersionRequestV2 build() { 26 | SetSecretVersionRequestV2 request = autoBuild(); 27 | if (request.name().isEmpty()) { 28 | throw new IllegalStateException("name is empty"); 29 | } 30 | return request; 31 | } 32 | } 33 | 34 | /** Static factory method used by Jackson for deserialization */ 35 | @SuppressWarnings("unused") 36 | @JsonCreator 37 | public static SetSecretVersionRequestV2 fromParts( 38 | @JsonProperty("name") String name, @JsonProperty("version") long version) { 39 | return builder().name(name).version(version).build(); 40 | } 41 | 42 | @JsonProperty("name") 43 | public abstract String name(); 44 | 45 | @JsonProperty("version") 46 | public abstract long version(); 47 | 48 | @Override 49 | public final String toString() { 50 | return MoreObjects.toStringHelper(this) 51 | .add("name", name()) 52 | .add("version", version()) 53 | .omitNullValues() 54 | .toString(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) 5 | and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). 6 | 7 | ## [Unreleased] 8 | ### Changed 9 | 10 | ## [1.3.0] - 2018-06-12 11 | ### Added 12 | - Support for all lower environments. 13 | 14 | ### Changed 15 | - Increased the auth token expiry time to 2 hours. 16 | - Increased max secrets size to 350KB. 17 | - Updated to latest dependencies. 18 | - Updated java doc. 19 | 20 | ### Fixed 21 | - Secret size validation error. 22 | 23 | ## [1.2.1] - 2018-05-14 24 | ### Changed 25 | - Increased max secrets size to 250KB. 26 | 27 | ### Added 28 | - Secrets cli version check on server side. 29 | 30 | ## [1.2.0] - 2018-05-04 31 | ### Fixed 32 | - AD authentication issue. 33 | - `.json` and `.xml` secrets upload issue. 34 | - Can't delete secrets with space in it. 35 | 36 | ### Changed 37 | - New docker image. 38 | - Applied Google code formatting 39 | - Updated to latest dependencies 40 | - Updated to latest swagger doc 41 | - Updated java doc. 42 | - Changed pom.xml to upload artifacts to Maven central 43 | 44 | 45 | ## [1.1.0] - 2017-09-05 46 | ### Fixed 47 | - Misc bug fixes. 48 | 49 | ## [1.0.0] - 2017-08-10 50 | ### Added 51 | - Initial release. 52 | 53 | 54 | 55 | [Unreleased]: https://github.com/oneops/secrets-proxy/compare/release-1.3.0...HEAD 56 | [1.3.0]: https://github.com/oneops/secrets-proxy/compare/release-1.2.1...release-1.3.0 57 | [1.2.1]: https://github.com/oneops/secrets-proxy/compare/release-1.2.0...release-1.2.1 58 | [1.2.0]: https://github.com/oneops/secrets-proxy/compare/1.1.0...release-1.2.0 59 | [1.1.0]: https://github.com/oneops/secrets-proxy/compare/1.0.0...1.1.0 60 | [1.0.0]: https://github.com/oneops/secrets-proxy/compare/f6900edc7077c6052d6417ebf69c8481329cef77...1.0.0 -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/security/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.security (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.security

14 |
15 |

Classes

16 | 24 |

Enums

25 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/KeywhizException.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.keywhiz; 19 | 20 | import java.io.IOException; 21 | 22 | /** 23 | * A custom checked exception to report keywhiz errors. 24 | * 25 | * @author Suresh 26 | */ 27 | public class KeywhizException extends IOException { 28 | 29 | private final int statusCode; 30 | 31 | /** 32 | * A constructor. 33 | * 34 | * @param statusCode Http status code. 35 | * @param message Exception message. 36 | */ 37 | public KeywhizException(int statusCode, String message) { 38 | super(message); 39 | this.statusCode = statusCode; 40 | } 41 | 42 | /** 43 | * Another constructor. 44 | * 45 | * @param statusCode Http status code. 46 | * @param message Exception message. 47 | * @param cause The cause. 48 | */ 49 | public KeywhizException(int statusCode, String message, Throwable cause) { 50 | super(message, cause); 51 | this.statusCode = statusCode; 52 | } 53 | 54 | /** Http status code that caused this exception. */ 55 | public int getStatusCode() { 56 | return statusCode; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/endpoint/KeywhizEndPoint.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.endpoint; 19 | 20 | import com.oneops.proxy.keywhiz.KeywhizAutomationClient; 21 | import java.io.IOException; 22 | import java.util.*; 23 | import org.springframework.boot.actuate.endpoint.AbstractEndpoint; 24 | import org.springframework.stereotype.Component; 25 | 26 | /** 27 | * Custom actuator endpoint (/keywhiz) to display keywhiz status. 28 | * 29 | * @author Suresh G 30 | */ 31 | @Component 32 | public class KeywhizEndPoint extends AbstractEndpoint> { 33 | 34 | private final KeywhizAutomationClient kwClient; 35 | 36 | public KeywhizEndPoint(KeywhizAutomationClient kwClient) { 37 | super("keywhiz", false, true); 38 | this.kwClient = kwClient; 39 | } 40 | 41 | @Override 42 | public Map invoke() { 43 | try { 44 | return kwClient.getStatus(); 45 | } catch (IOException e) { 46 | Map err = new HashMap<>(); 47 | err.put("status", "down"); 48 | err.put("message", e.getMessage()); 49 | return err; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/auth/login/LoginFailureHandler.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.auth.login; 19 | 20 | import com.oneops.proxy.auth.token.TokenAuthProvider; 21 | import java.io.IOException; 22 | import javax.servlet.ServletException; 23 | import javax.servlet.http.*; 24 | import org.springframework.security.core.AuthenticationException; 25 | import org.springframework.security.web.authentication.AuthenticationFailureHandler; 26 | import org.springframework.stereotype.Component; 27 | 28 | /** 29 | * Invoked by {@link LoginAuthProvider} or {@link TokenAuthProvider} in case of authentication 30 | * failures. Need to send proper JSON error responses in future. 31 | * 32 | * @author Suresh G 33 | */ 34 | @Component 35 | public class LoginFailureHandler implements AuthenticationFailureHandler { 36 | 37 | @Override 38 | public void onAuthenticationFailure( 39 | HttpServletRequest req, HttpServletResponse res, AuthenticationException exception) 40 | throws IOException, ServletException { 41 | res.sendError( 42 | HttpServletResponse.SC_UNAUTHORIZED, "Authentication Failed: " + exception.getMessage()); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/model/SecretContent.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.model; 19 | 20 | import com.fasterxml.jackson.annotation.*; 21 | 22 | /** 23 | * Secret content response. 24 | * 25 | * @author Suresh G 26 | */ 27 | public class SecretContent { 28 | 29 | @JsonProperty private String name; 30 | 31 | @JsonProperty private String content; 32 | 33 | @JsonCreator 34 | public SecretContent(String name, String content) { 35 | this.name = name; 36 | this.content = content; 37 | } 38 | 39 | public static SecretContent from(String uniqSecretName, String content) { 40 | AppSecret appSecret = new AppSecret(uniqSecretName); 41 | return new SecretContent(appSecret.getSecretName(), content); 42 | } 43 | 44 | public String getName() { 45 | return name; 46 | } 47 | 48 | public void setName(String name) { 49 | this.name = name; 50 | } 51 | 52 | public String getContent() { 53 | return content; 54 | } 55 | 56 | public void setContent(String content) { 57 | this.content = content; 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "SecretContent{" + "name='" + name + '\'' + '}'; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /contrib/init/systemd/keywhiz-proxy-env: -------------------------------------------------------------------------------- 1 | # Default Secrets and Log directory 2 | # --------------------------------- 3 | SECRETS_DIR=/secrets 4 | LOGGING_PATH=/log 5 | 6 | # Keywhiz Proxy Server config 7 | # --------------------------- 8 | SERVER_SSL_KEY_STORE=file:${SECRETS_DIR}/keywhiz_proxy_keystore.p12 9 | SERVER_SSL_KEY_PASSWORD=xxxxx 10 | SERVER_SSL_KEY_STORE_PASSWORD=xxxxx 11 | 12 | # Keywhiz Server and Automation Client config 13 | # ------------------------------------------- 14 | ONEOPS_KEYWHIZ_BASE_URL=https://keywhiz.com:4444/ 15 | ONEOPS_KEYWHIZ_TRUST_STORE_PATH=file:${SECRETS_DIR}/keywhiz_truststore.p12 16 | ONEOPS_KEYWHIZ_TRUST_STORE_STORE_PASSWORD=xxxxx 17 | ONEOPS_KEYWHIZ_KEY_STORE_PATH=file:${SECRETS_DIR}/keywhiz_keystore.p12 18 | ONEOPS_KEYWHIZ_KEY_STORE_STORE_PASSWORD=xxxxx 19 | ONEOPS_KEYWHIZ_KEY_STORE_KEY_PASSWORD=xxxxx 20 | ONEOPS_KEYWHIZ_SECRET_MAX_SIZE=350000 21 | ONEOPS_KEYWHIZ_CLI_DOWNLOAD_URL=https://secrets.oneops.com/cli/download 22 | ONEOPS_KEYWHIZ_CLI_USER_AGENT_HEADER=OneOpsSecretsCLI- 23 | 24 | # AD/LDAP Server Config 25 | # --------------------- 26 | ONEOPS_LDAP_SERVER=ldap://ldap.com 27 | ONEOPS_LDAP_USER_BASE_DN=dc=xxxxx,dc=xxxxx,dc=com 28 | ONEOPS_LDAP_USER_DN=CN=xxxxx,DC=xxxxx,DC=xxxxx,DC=com 29 | ONEOPS_LDAP_PASSWORD=xxxxx 30 | ONEOPS_LDAP_TRUST_STORE_PATH=file:${SECRETS_DIR}/ldap_truststore.p12 31 | ONEOPS_LDAP_TRUST_STORE_STORE_PASSWORD=xxxxx 32 | 33 | # Keywhiz Proxy Token Auth Config 34 | # ------------------------------- 35 | ONEOPS_AUTH_SIGNING_KEY=xxxxx 36 | ONEOPS_AUTH_EXPIRES_IN_SEC=xxxxx 37 | 38 | # OneOps User Datasource config 39 | # ----------------------------- 40 | ONEOPS_PROD_DB_URL=jdbc:postgresql://prod-userdb:5432/xxxxx 41 | ONEOPS_MGMT_DB_URL=jdbc:postgresql://mgmt-userdb:5432/xxxxx 42 | ONEOPS_STG_DB_URL=jdbc:postgresql://stg-userdb:5432/xxxxx 43 | ONEOPS_DEV_DB_URL=jdbc:postgresql://dev-userdb:5432/xxxxx 44 | ONEOPS_DB_USER=xxxxxx 45 | ONEOPS_DB_PASS=xxxxxx 46 | 47 | # Management app config 48 | # --------------------- 49 | MANAGEMENT_USER=xxxxx 50 | MANAGEMENT_PASSWORD=xxxxx 51 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/config/PropertyVerifier.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.config; 19 | 20 | import org.springframework.beans.BeansException; 21 | import org.springframework.beans.factory.config.*; 22 | import org.springframework.context.ApplicationContextException; 23 | import org.springframework.core.PriorityOrdered; 24 | import org.springframework.core.env.Environment; 25 | 26 | /** 27 | * A verifier bean for keywhiz application properties. The property verifier is configured to 28 | * process first and will validate the application specific properties. 29 | * 30 | * @author Suresh 31 | */ 32 | public class PropertyVerifier implements BeanFactoryPostProcessor, PriorityOrdered { 33 | 34 | @Override 35 | public void postProcessBeanFactory(final ConfigurableListableBeanFactory beanFactory) 36 | throws BeansException { 37 | Environment env = beanFactory.getBean(Environment.class); 38 | String propName = "oneops.keywhiz.baseUrl"; 39 | if (env.getProperty(propName) != null) { 40 | throw new ApplicationContextException("Missing property on bootstrap, " + propName); 41 | } 42 | } 43 | 44 | @Override 45 | public int getOrder() { 46 | return HIGHEST_PRECEDENCE; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docs/apidocs/oauth2-redirect.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 54 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/config/MgmtConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.config; 19 | 20 | import org.springframework.boot.SpringBootVersion; 21 | import org.springframework.boot.actuate.autoconfigure.ExportMetricWriter; 22 | import org.springframework.boot.actuate.info.InfoContributor; 23 | import org.springframework.boot.actuate.metrics.jmx.JmxMetricWriter; 24 | import org.springframework.boot.actuate.metrics.writer.MetricWriter; 25 | import org.springframework.context.annotation.*; 26 | import org.springframework.jmx.export.MBeanExporter; 27 | 28 | /** 29 | * Application management bean configurations. Mainly used for configuring actuators. 30 | * 31 | * @author Suresh 32 | */ 33 | @Configuration 34 | public class MgmtConfig { 35 | 36 | /** 37 | * Contribute SpringBoot version to "/info". 38 | * 39 | * @return {@link InfoContributor} 40 | */ 41 | @Bean 42 | public InfoContributor versionInfo() { 43 | return builder -> builder.withDetail("spring-boot.version", SpringBootVersion.getVersion()); 44 | } 45 | 46 | /** Exports actuator metrics to JMX. */ 47 | @Bean 48 | @ExportMetricWriter 49 | public MetricWriter metricWriter(MBeanExporter exporter) { 50 | return new JmxMetricWriter(exporter); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/SecretContentsResponseV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.google.auto.value.AutoValue; 5 | import com.google.common.collect.*; 6 | import java.util.*; 7 | 8 | @AutoValue 9 | public abstract class SecretContentsResponseV2 { 10 | SecretContentsResponseV2() {} // prevent sub-classing 11 | 12 | public static Builder builder() { 13 | return new AutoValue_SecretContentsResponseV2.Builder() 14 | .successSecrets(ImmutableMap.of()) 15 | .missingSecrets(ImmutableList.of()); 16 | } 17 | 18 | @AutoValue.Builder 19 | public abstract static class Builder { 20 | // intended to be package-private 21 | abstract SecretContentsResponseV2.Builder successSecrets( 22 | ImmutableMap successSecrets); 23 | 24 | abstract SecretContentsResponseV2.Builder missingSecrets(ImmutableList missingSecrets); 25 | 26 | public SecretContentsResponseV2.Builder successSecrets(Map successSecrets) { 27 | return successSecrets(ImmutableMap.copyOf(successSecrets)); 28 | } 29 | 30 | public SecretContentsResponseV2.Builder missingSecrets(List missingSecrets) { 31 | return missingSecrets(ImmutableList.copyOf(missingSecrets)); 32 | } 33 | 34 | public abstract SecretContentsResponseV2 build(); 35 | } 36 | 37 | /** Static factory method used by Jackson for deserialization */ 38 | @SuppressWarnings("unused") 39 | @JsonCreator 40 | public static SecretContentsResponseV2 fromParts( 41 | @JsonProperty("successSecrets") ImmutableMap successSecrets, 42 | @JsonProperty("missingSecrets") ImmutableList missingSecrets) { 43 | return builder().successSecrets(successSecrets).missingSecrets(missingSecrets).build(); 44 | } 45 | 46 | @JsonProperty("successSecrets") 47 | public abstract ImmutableMap successSecrets(); 48 | 49 | @JsonProperty("missingSecrets") 50 | public abstract ImmutableList missingSecrets(); 51 | } 52 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/model/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.model (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.model

14 |
15 |

Classes

16 | 28 |
29 | 30 | 31 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/CreateGroupRequestV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import static com.google.common.base.Strings.nullToEmpty; 4 | 5 | import com.fasterxml.jackson.annotation.*; 6 | import com.google.auto.value.AutoValue; 7 | import com.google.common.collect.ImmutableMap; 8 | import javax.annotation.Nullable; 9 | 10 | @AutoValue 11 | public abstract class CreateGroupRequestV2 { 12 | CreateGroupRequestV2() {} // prevent sub-classing 13 | 14 | public static Builder builder() { 15 | return new AutoValue_CreateGroupRequestV2.Builder().description("").metadata(ImmutableMap.of()); 16 | } 17 | 18 | @AutoValue.Builder 19 | public abstract static class Builder { 20 | public abstract Builder name(String name); 21 | 22 | public abstract Builder description(String description); 23 | 24 | public abstract Builder metadata(ImmutableMap metadata); 25 | 26 | abstract CreateGroupRequestV2 autoBuild(); 27 | 28 | public CreateGroupRequestV2 build() { 29 | CreateGroupRequestV2 request = autoBuild(); 30 | if (request.name().isEmpty()) { 31 | throw new IllegalStateException("name is empty"); 32 | } 33 | return request; 34 | } 35 | } 36 | 37 | /** Static factory method used by Jackson for deserialization */ 38 | @SuppressWarnings("unused") 39 | @JsonCreator 40 | public static CreateGroupRequestV2 fromParts( 41 | @JsonProperty("name") String name, 42 | @JsonProperty("description") @Nullable String description, 43 | @JsonProperty("metadata") @Nullable ImmutableMap metadata) { 44 | return builder() 45 | .name(name) 46 | .description(nullToEmpty(description)) 47 | .metadata(ImmutableMap.copyOf(metadata == null ? ImmutableMap.of() : metadata)) 48 | .build(); 49 | } 50 | 51 | @JsonProperty("name") 52 | public abstract String name(); 53 | 54 | @JsonProperty("description") 55 | public abstract String description(); 56 | 57 | @JsonProperty("metadata") 58 | public abstract ImmutableMap metadata(); 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/security/annotations/AuthorizeGroup.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.security.annotations; 19 | 20 | import static java.lang.annotation.ElementType.*; 21 | import static java.lang.annotation.RetentionPolicy.RUNTIME; 22 | 23 | import com.oneops.proxy.auth.user.OneOpsUser; 24 | import com.oneops.proxy.authz.Authz; 25 | import java.lang.annotation.*; 26 | import org.springframework.security.access.prepost.PreAuthorize; 27 | 28 | /** 29 | * A meta annotation to enable Spring security's Pre-Authorization check for all the secure resource 30 | * access. It's configured to invoke {@link Authz#isAuthorized(String, OneOpsUser)} with oneops 31 | * application name and the current authenticated {@link OneOpsUser} as arguments. 32 | * 33 | *

    34 | *
  • appName is the OneOps application name. 35 | *
  • principal is the current authenticated user, provided by spring security. 36 | *
37 | * 38 | * {@link PreAuthorize} uses Spring Expression Language (SPEL) to invoke the {@link 39 | * Authz#isAuthorized(String, OneOpsUser)} method. 40 | * 41 | * @author Suresh G 42 | */ 43 | @Target({METHOD, TYPE}) 44 | @Retention(RUNTIME) 45 | @PreAuthorize("@authz.isAuthorized(#appName,principal)") 46 | public @interface AuthorizeGroup {} 47 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/auth/token/SkipPathRequestMatcher.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.auth.token; 19 | 20 | import java.util.List; 21 | import java.util.stream.Collectors; 22 | import javax.annotation.Nonnull; 23 | import javax.servlet.http.HttpServletRequest; 24 | import org.slf4j.*; 25 | import org.springframework.security.web.util.matcher.*; 26 | 27 | /** 28 | * Request paths matcher configured to skip endpoints for {@link TokenAuthProcessingFilter} By 29 | * default it's configured to skip management endpoints. 30 | * 31 | * @author Suresh 32 | */ 33 | public class SkipPathRequestMatcher implements RequestMatcher { 34 | 35 | private final Logger log = LoggerFactory.getLogger(getClass()); 36 | 37 | private final OrRequestMatcher matcher; 38 | 39 | public SkipPathRequestMatcher(@Nonnull List pathsToSkip) { 40 | log.info("Initializing Skip path request matchers for " + pathsToSkip); 41 | List pathMatchers = 42 | pathsToSkip.stream().map(AntPathRequestMatcher::new).collect(Collectors.toList()); 43 | this.matcher = new OrRequestMatcher(pathMatchers); 44 | } 45 | 46 | @Override 47 | public boolean matches(HttpServletRequest request) { 48 | // Skip any http requests matching pathsToSkip. 49 | return !matcher.matches(request); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/security/RestAuthEntryPoint.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.security; 19 | 20 | import static com.oneops.proxy.config.Constants.APP_NAME; 21 | import static org.springframework.http.HttpHeaders.WWW_AUTHENTICATE; 22 | import static org.springframework.http.HttpStatus.UNAUTHORIZED; 23 | 24 | import java.io.IOException; 25 | import javax.servlet.ServletException; 26 | import javax.servlet.http.*; 27 | import org.springframework.security.core.AuthenticationException; 28 | import org.springframework.security.web.AuthenticationEntryPoint; 29 | import org.springframework.security.web.access.ExceptionTranslationFilter; 30 | import org.springframework.stereotype.Component; 31 | 32 | /** 33 | * Authentication entry point bean to commences an authentication scheme on {@link 34 | * ExceptionTranslationFilter}. 35 | * 36 | * @author Suresh 37 | */ 38 | @Component 39 | public class RestAuthEntryPoint implements AuthenticationEntryPoint { 40 | 41 | @Override 42 | public void commence( 43 | HttpServletRequest req, HttpServletResponse res, AuthenticationException authException) 44 | throws IOException, ServletException { 45 | res.addHeader(WWW_AUTHENTICATE, "Basic realm=\"" + APP_NAME + "\""); 46 | res.sendError(UNAUTHORIZED.value(), authException.getMessage()); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/web/RootController.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.web; 19 | 20 | import static com.oneops.proxy.config.Constants.APP_NAME; 21 | 22 | import com.oneops.proxy.model.RootResponse; 23 | import io.swagger.annotations.*; 24 | import java.io.IOException; 25 | import javax.servlet.http.HttpServletResponse; 26 | import org.springframework.beans.factory.annotation.Value; 27 | import org.springframework.web.bind.annotation.*; 28 | 29 | /** 30 | * Application root controller. 31 | * 32 | * @author Suresh 33 | */ 34 | @RestController 35 | @Api(value = "Root EndPoint", description = "Secrets Proxy and API doc info.") 36 | public class RootController { 37 | 38 | /** Maven artifact version. */ 39 | @Value("${info.version}") 40 | private String version; 41 | 42 | /** Application info. */ 43 | @GetMapping(path = "/") 44 | @ApiOperation(value = "Version Info", notes = "Token header is not required for this request.") 45 | public RootResponse info() { 46 | return new RootResponse(APP_NAME, version); 47 | } 48 | 49 | /** Redirect to Swagger API doc. */ 50 | @GetMapping(path = "/apidocs") 51 | @ApiOperation(value = "Swagger API Doc", notes = "Token header is not required for this request.") 52 | public void apiDoc(HttpServletResponse res) throws IOException { 53 | res.sendRedirect("/swagger-ui.html"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/CreateGroupRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.common.base.Objects; 21 | import com.google.common.collect.ImmutableMap; 22 | import javax.annotation.Nullable; 23 | 24 | public class CreateGroupRequest { 25 | 26 | @JsonProperty public final String name; 27 | 28 | @Nullable @JsonProperty public final String description; 29 | 30 | @Nullable @JsonProperty public final ImmutableMap metadata; 31 | 32 | public CreateGroupRequest( 33 | @JsonProperty("name") String name, 34 | @Nullable @JsonProperty("description") String description, 35 | @Nullable @JsonProperty("metadata") ImmutableMap metadata) { 36 | this.name = name; 37 | this.description = description; 38 | this.metadata = metadata == null ? ImmutableMap.of() : ImmutableMap.copyOf(metadata); 39 | } 40 | 41 | @Override 42 | public int hashCode() { 43 | return Objects.hashCode(name, description, metadata); 44 | } 45 | 46 | @Override 47 | public boolean equals(Object o) { 48 | if (this == o) return true; 49 | if (o instanceof CreateGroupRequest) { 50 | CreateGroupRequest that = (CreateGroupRequest) o; 51 | if (Objects.equal(this.name, that.name) 52 | && Objects.equal(this.description, that.description) 53 | && Objects.equal(this.metadata, that.metadata)) { 54 | return true; 55 | } 56 | } 57 | return false; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/resources/logback-spring.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ${LOG_PATH}/${LOG_FILE}.log 10 | 11 | ${FILE_LOG_PATTERN} 12 | 13 | 14 | 15 | ${LOG_PATH}/archived/${LOG_FILE}-%d{yyyy-MM-dd}.%i.log.zip 16 | 17 | 50MB 18 | 14 19 | 2GB 20 | 21 | 22 | 23 | 24 | 25 | ${LOG_PATH}/audit/${AUDIT_LOG_FILE}.log 26 | 27 | %date{dd/MMM/yyyy:HH:mm:ss.SSS} - %msg%n 28 | 29 | 30 | ${LOG_PATH}/audit/${AUDIT_LOG_FILE}-%d{yyyy-MM-dd}.%i.log.zip 31 | 10MB 32 | 90 33 | 2GB 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/security/CliVersionFilter.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.security; 2 | 3 | import com.oneops.proxy.config.OneOpsConfig; 4 | import java.io.IOException; 5 | import java.util.*; 6 | import javax.servlet.*; 7 | import javax.servlet.http.*; 8 | import org.slf4j.*; 9 | import org.springframework.security.core.context.SecurityContextHolder; 10 | import org.springframework.web.filter.GenericFilterBean; 11 | 12 | /** 13 | * A security filter to validate compatible secrets cli version. 14 | * 15 | * @author Suresh 16 | */ 17 | public class CliVersionFilter extends GenericFilterBean { 18 | 19 | private final Logger log = LoggerFactory.getLogger(getClass()); 20 | 21 | private OneOpsConfig.Cli cliConfig; 22 | 23 | public CliVersionFilter(OneOpsConfig config) { 24 | this.cliConfig = config.getKeywhiz().getCli(); 25 | } 26 | 27 | @Override 28 | public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) 29 | throws IOException, ServletException { 30 | HttpServletRequest httpReq = asHttp(req); 31 | HttpServletResponse httpRes = asHttp(res); 32 | 33 | Optional uaHeader = Optional.ofNullable(httpReq.getHeader("User-Agent")); 34 | if (uaHeader.isPresent()) { 35 | String userAgent = uaHeader.get(); 36 | String userAgentPrefix = cliConfig.getUserAgentHeader(); 37 | if (userAgent.startsWith(userAgentPrefix)) { 38 | String version = userAgent.replaceFirst(userAgentPrefix, ""); 39 | if (!Objects.equals(version, cliConfig.getVersion())) { 40 | String msg = 41 | "The secrets cli (v" 42 | + version 43 | + ") you are using is deprecated. Please download the latest version from " 44 | + cliConfig.getDownloadUrl(); 45 | log.error("CLI version {} not supported.", version); 46 | SecurityContextHolder.clearContext(); 47 | httpRes.sendError(HttpServletResponse.SC_UNAUTHORIZED, msg); 48 | return; 49 | } 50 | } 51 | } 52 | chain.doFilter(req, res); 53 | } 54 | 55 | private HttpServletRequest asHttp(ServletRequest request) { 56 | return (HttpServletRequest) request; 57 | } 58 | 59 | private HttpServletResponse asHttp(ServletResponse response) { 60 | return (HttpServletResponse) response; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/config/Constants.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.config; 19 | 20 | import static com.oneops.proxy.model.AppGroup.APP_NAME_PARAM; 21 | 22 | /** 23 | * Constants used in the application. 24 | * 25 | * @author Suresh 26 | */ 27 | public interface Constants { 28 | 29 | /** App name used in responses. */ 30 | String APP_NAME = "OneOps Secrets Management."; 31 | 32 | /** Current Rest API version. */ 33 | String API_VERSION = "v1"; 34 | 35 | /** {@link com.oneops.proxy.web.AuthController} base path URI. */ 36 | String AUTH_CTLR_BASE_PATH = "/" + API_VERSION + "/auth"; 37 | 38 | /** {@link com.oneops.proxy.web.CliController} base path URI. */ 39 | String CLI_CTLR_BASE_PATH = "/cli"; 40 | 41 | /** Authentication token path URI. */ 42 | String AUTH_TOKEN_URI = AUTH_CTLR_BASE_PATH + "/token"; 43 | 44 | /** {@link com.oneops.proxy.web.GroupController} base path URI. */ 45 | String GROUP_CTLR_BASE_PATH = "/" + API_VERSION + "/apps/" + "{" + APP_NAME_PARAM + "}"; 46 | 47 | /** Favicon path, for browser agents. */ 48 | String FAVICON_PATH = "/favicon.ico"; 49 | 50 | /** Default access token type (Eg: Bearer, JWT etc) */ 51 | String DEFAULT_TOKEN_TYPE = "Bearer"; 52 | 53 | /** Default paths to skip from security and authentication. */ 54 | String[] DEFAULT_SKIP_PATHS = { 55 | "/", 56 | FAVICON_PATH, 57 | "/apidocs", 58 | "/swagger-ui.html**", 59 | "/v2/api-docs", 60 | "/webjars/**", 61 | "/swagger-resources/**", 62 | "/cli/**" 63 | }; 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/CreateClientRequestV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import static com.google.common.base.Strings.nullToEmpty; 4 | 5 | import com.fasterxml.jackson.annotation.*; 6 | import com.google.auto.value.AutoValue; 7 | import com.google.common.collect.ImmutableSet; 8 | import javax.annotation.Nullable; 9 | 10 | /** 11 | * Model for request to create a new keywhiz client. 12 | * 13 | *

Note: renamed from CreateClientRequest because swagger docs do not handle class name 14 | * collisions. 15 | */ 16 | @AutoValue 17 | public abstract class CreateClientRequestV2 { 18 | CreateClientRequestV2() {} // prevent sub-classing 19 | 20 | public static Builder builder() { 21 | return new AutoValue_CreateClientRequestV2.Builder().groups().description(""); 22 | } 23 | 24 | @AutoValue.Builder 25 | public abstract static class Builder { 26 | // intended to be package-private 27 | abstract Builder groups(ImmutableSet groups); 28 | 29 | public abstract Builder description(String description); 30 | 31 | public abstract Builder name(String name); 32 | 33 | abstract CreateClientRequestV2 autoBuild(); 34 | 35 | public Builder groups(String... groups) { 36 | return groups(ImmutableSet.copyOf(groups)); 37 | } 38 | 39 | public CreateClientRequestV2 build() { 40 | CreateClientRequestV2 request = autoBuild(); 41 | if (request.name().isEmpty()) { 42 | throw new IllegalStateException("name is empty"); 43 | } 44 | return request; 45 | } 46 | } 47 | 48 | /** Static factory method used by Jackson for deserialization */ 49 | @SuppressWarnings("unused") 50 | @JsonCreator 51 | public static CreateClientRequestV2 fromParts( 52 | @JsonProperty("name") String name, 53 | @JsonProperty("groups") Iterable groups, 54 | @JsonProperty("description") @Nullable String description) { 55 | return builder() 56 | .name(name) 57 | .groups(ImmutableSet.copyOf(groups)) 58 | .description(nullToEmpty(description)) 59 | .build(); 60 | } 61 | 62 | @JsonProperty("name") 63 | public abstract String name(); 64 | 65 | @JsonProperty("groups") 66 | public abstract ImmutableSet groups(); 67 | 68 | @JsonProperty("description") 69 | public abstract String description(); 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/config/CacheConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.config; 19 | 20 | import com.github.benmanes.caffeine.cache.CaffeineSpec; 21 | import org.slf4j.*; 22 | import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizer; 23 | import org.springframework.cache.annotation.EnableCaching; 24 | import org.springframework.cache.caffeine.CaffeineCacheManager; 25 | import org.springframework.context.annotation.*; 26 | 27 | /** 28 | * Cache manager customizer. The proxy application by default using the awesome Caffeine cache 29 | * provider. 30 | * 31 | * @author Suresh G 32 | */ 33 | @Configuration 34 | @EnableCaching 35 | public class CacheConfig { 36 | 37 | private final Logger log = LoggerFactory.getLogger(getClass()); 38 | 39 | /** 40 | * Tunes the auto configured Cache manager. 41 | * 42 | * @return {@link CacheManagerCustomizer} 43 | */ 44 | @Bean 45 | public CacheManagerCustomizer cacheManagerCustomizer() { 46 | return cacheManager -> cacheManager.setAllowNullValues(false); 47 | } 48 | 49 | /** 50 | * Default cache spec configuration for all the caches. The default cache size is 200 and would 51 | * expire after a min (60sec) of write operation. 52 | * 53 | * @return {@link CaffeineSpec} 54 | */ 55 | @Bean 56 | public CaffeineSpec caffeineSpec() { 57 | CaffeineSpec spec = CaffeineSpec.parse("maximumSize=200,expireAfterWrite=300s"); 58 | log.info("Using CaffeineSpec " + spec.toParsableString()); 59 | return spec; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/ClientDetailResponseV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.google.auto.value.AutoValue; 5 | import com.oneops.proxy.keywhiz.model.*; 6 | import java.util.Optional; 7 | 8 | @AutoValue 9 | public abstract class ClientDetailResponseV2 { 10 | 11 | ClientDetailResponseV2() {} // prevent sub-classing 12 | 13 | public static ClientDetailResponseV2 fromClient(Client client) { 14 | Optional lastSeen = Optional.ofNullable(client.getLastSeen()); 15 | 16 | return new AutoValue_ClientDetailResponseV2( 17 | client.getName(), 18 | client.getDescription(), 19 | client.getCreatedAt().toEpochSecond(), 20 | client.getUpdatedAt().toEpochSecond(), 21 | client.getCreatedBy(), 22 | client.getUpdatedBy(), 23 | lastSeen.map(ApiDate::toEpochSecond)); 24 | } 25 | 26 | /** Static factory method used by Jackson for deserialization */ 27 | @SuppressWarnings("unused") 28 | @JsonCreator 29 | public static ClientDetailResponseV2 fromParts( 30 | @JsonProperty("name") String name, 31 | @JsonProperty("description") String description, 32 | @JsonProperty("createdAtSeconds") long createdAtSeconds, 33 | @JsonProperty("updatedAtSeconds") long updatedAtSeconds, 34 | @JsonProperty("createdBy") String createdBy, 35 | @JsonProperty("updatedBy") String updatedBy, 36 | @JsonProperty("lastSeenSeconds") Optional lastSeenSeconds) { 37 | return new AutoValue_ClientDetailResponseV2( 38 | name, 39 | description, 40 | createdAtSeconds, 41 | updatedAtSeconds, 42 | createdBy, 43 | updatedBy, 44 | lastSeenSeconds); 45 | } 46 | 47 | @JsonProperty("name") 48 | public abstract String name(); 49 | 50 | @JsonProperty("description") 51 | public abstract String description(); 52 | 53 | @JsonProperty("createdAtSeconds") 54 | public abstract long createdAtSeconds(); 55 | 56 | @JsonProperty("updatedAtSeconds") 57 | public abstract long updatedAtSeconds(); 58 | 59 | @JsonProperty("createdBy") 60 | public abstract String createdBy(); 61 | 62 | @JsonProperty("updatedBy") 63 | public abstract String updatedBy(); 64 | 65 | @JsonProperty("lastSeenSeconds") 66 | public abstract Optional lastSeenSeconds(); 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/security/GlobalSecurityConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.security; 19 | 20 | import static org.springframework.core.Ordered.HIGHEST_PRECEDENCE; 21 | 22 | import org.slf4j.*; 23 | import org.springframework.context.annotation.Configuration; 24 | import org.springframework.core.annotation.Order; 25 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 26 | import org.springframework.security.config.annotation.authentication.configurers.GlobalAuthenticationConfigurerAdapter; 27 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 28 | 29 | /** 30 | * A Global authentication manager(AM) config for the application. This configuration also enables 31 | * the Spring security Pre/Post authorization on methods. 32 | * 33 | * @author Suresh 34 | */ 35 | @Configuration 36 | @Order(HIGHEST_PRECEDENCE) 37 | @EnableGlobalMethodSecurity(prePostEnabled = true) 38 | public class GlobalSecurityConfig extends GlobalAuthenticationConfigurerAdapter { 39 | 40 | private static final Logger log = LoggerFactory.getLogger(GlobalSecurityConfig.class); 41 | 42 | /** 43 | * This is a workaround to avoid generating default password as an InMemoryAuthentication 44 | * manager is already configured in {@link WebSecurityConfig}. 45 | */ 46 | @Override 47 | public void init(AuthenticationManagerBuilder auth) throws Exception { 48 | log.info("Configuring global authentication manager."); 49 | auth.inMemoryAuthentication(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/model/LoginResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.model; 19 | 20 | import static com.oneops.proxy.config.Constants.DEFAULT_TOKEN_TYPE; 21 | 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | 24 | /** 25 | * Login response. 26 | * 27 | * @author Suresh 28 | */ 29 | public class LoginResponse { 30 | 31 | @JsonProperty private String accessToken; 32 | 33 | @JsonProperty private String tokenType = DEFAULT_TOKEN_TYPE; 34 | 35 | @JsonProperty private int expiresInSec; 36 | 37 | public LoginResponse(String accessToken, String tokenType, int expiresInSec) { 38 | this.accessToken = accessToken; 39 | this.tokenType = tokenType; 40 | this.expiresInSec = expiresInSec; 41 | } 42 | 43 | public String getAccessToken() { 44 | return accessToken; 45 | } 46 | 47 | public void setAccessToken(String accessToken) { 48 | this.accessToken = accessToken; 49 | } 50 | 51 | public String getTokenType() { 52 | return tokenType; 53 | } 54 | 55 | public void setTokenType(String tokenType) { 56 | this.tokenType = tokenType; 57 | } 58 | 59 | public int getExpiresInSec() { 60 | return expiresInSec; 61 | } 62 | 63 | public void setExpiresInSec(int expiresInSec) { 64 | this.expiresInSec = expiresInSec; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return "LoginResponse{" 70 | + "accessToken=******" 71 | + ", tokenType='" 72 | + tokenType 73 | + '\'' 74 | + ", expiresInSec=" 75 | + expiresInSec 76 | + '}'; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/generated/java/com/oneops/user/tables/SchemaMigrations.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package com.oneops.user.tables; 5 | 6 | import com.oneops.user.Public; 7 | import com.oneops.user.tables.records.SchemaMigrationsRecord; 8 | import org.jooq.*; 9 | import org.jooq.impl.TableImpl; 10 | 11 | import javax.annotation.Generated; 12 | 13 | /** This class is generated by jOOQ. */ 14 | @Generated( 15 | value = {"http://www.jooq.org", "jOOQ version:3.9.2"}, 16 | comments = "This class is generated by jOOQ" 17 | ) 18 | @SuppressWarnings({"all", "unchecked", "rawtypes"}) 19 | public class SchemaMigrations extends TableImpl { 20 | 21 | private static final long serialVersionUID = 2001250329; 22 | 23 | /** The reference instance of public.schema_migrations */ 24 | public static final SchemaMigrations SCHEMA_MIGRATIONS = new SchemaMigrations(); 25 | 26 | /** The class holding records for this type */ 27 | @Override 28 | public Class getRecordType() { 29 | return SchemaMigrationsRecord.class; 30 | } 31 | 32 | /** The column public.schema_migrations.version. */ 33 | public final TableField VERSION = 34 | createField( 35 | "version", org.jooq.impl.SQLDataType.VARCHAR.length(255).nullable(false), this, ""); 36 | 37 | /** Create a public.schema_migrations table reference */ 38 | public SchemaMigrations() { 39 | this("schema_migrations", null); 40 | } 41 | 42 | /** Create an aliased public.schema_migrations table reference */ 43 | public SchemaMigrations(String alias) { 44 | this(alias, SCHEMA_MIGRATIONS); 45 | } 46 | 47 | private SchemaMigrations(String alias, Table aliased) { 48 | this(alias, aliased, null); 49 | } 50 | 51 | private SchemaMigrations( 52 | String alias, Table aliased, Field[] parameters) { 53 | super(alias, null, aliased, parameters, ""); 54 | } 55 | 56 | /** {@inheritDoc} */ 57 | @Override 58 | public Schema getSchema() { 59 | return Public.PUBLIC; 60 | } 61 | 62 | /** {@inheritDoc} */ 63 | @Override 64 | public SchemaMigrations as(String alias) { 65 | return new SchemaMigrations(alias, this); 66 | } 67 | 68 | /** Rename this table */ 69 | @Override 70 | public SchemaMigrations rename(String name) { 71 | return new SchemaMigrations(name, null); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/model/UserResponse.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.model; 19 | 20 | import com.oneops.proxy.authz.AuthDomain; 21 | import java.util.List; 22 | 23 | /** 24 | * Authenticated user response. 25 | * 26 | * @author Suresh G 27 | */ 28 | public class UserResponse { 29 | 30 | private String userName; 31 | 32 | private String cn; 33 | 34 | private AuthDomain domain; 35 | 36 | private List roles; 37 | 38 | public UserResponse(String userName, String cn, AuthDomain domain, List roles) { 39 | this.userName = userName; 40 | this.cn = cn; 41 | this.domain = domain; 42 | this.roles = roles; 43 | } 44 | 45 | public String getUserName() { 46 | return userName; 47 | } 48 | 49 | public void setUserName(String userName) { 50 | this.userName = userName; 51 | } 52 | 53 | public String getCn() { 54 | return cn; 55 | } 56 | 57 | public void setCn(String cn) { 58 | this.cn = cn; 59 | } 60 | 61 | public AuthDomain getDomain() { 62 | return domain; 63 | } 64 | 65 | public void setDomain(AuthDomain domain) { 66 | this.domain = domain; 67 | } 68 | 69 | public List getRoles() { 70 | return roles; 71 | } 72 | 73 | public void setRoles(List roles) { 74 | this.roles = roles; 75 | } 76 | 77 | @Override 78 | public String toString() { 79 | return "UserResponse{" 80 | + "userName='" 81 | + userName 82 | + '\'' 83 | + ", cn='" 84 | + cn 85 | + '\'' 86 | + ", domain='" 87 | + domain.getType() 88 | + '\'' 89 | + ", roles=" 90 | + roles 91 | + '}'; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /contrib/init/systemd/README.md: -------------------------------------------------------------------------------- 1 | ## Keywhiz Proxy Env Vars 2 | 3 | All the external configurations to run **Keywhiz Proxy** server are set in the [keywhiz-proxy-env](keywhiz-proxy-env) 4 | file. 5 | 6 | >In OneOps production setup, the actual env configuration file is securely stored in [Keywhiz](https://github.com/square/keywhiz) 7 | >and made available to running servers using Keywhiz client component under `/secrets` directory. 8 | 9 | The following are environment variables and it's description. 10 | 11 | #### Secrets and Logs Config 12 | 13 | * **SECRETS_DIR** - The directory to look for secrets files. Defaults to `/secrets`. 14 | * **LOGGING_PATH** - The directory for application/access/audit and runtime logs. Defaults to `/log`. 15 | 16 | #### Keywhiz Proxy Server config 17 | 18 | * **SERVER_SSL_KEY_STORE** - file:${SECRETS_DIR}/keywhiz_proxy_keystore.p12 19 | * **SERVER_SSL_KEY_PASSWORD** - xxxxx 20 | * **SERVER_SSL_KEY_STORE_PASSWORD** - xxxxx 21 | 22 | #### Keywhiz Server and Automation Client config 23 | 24 | * **ONEOPS_KEYWHIZ_BASE_URL** - https://keywhiz.com:4444/ 25 | * **ONEOPS_KEYWHIZ_TRUST_STORE_PATH** - file:${SECRETS_DIR}/keywhiz_truststore.p12 26 | * **ONEOPS_KEYWHIZ_TRUST_STORE_STORE_PASSWORD** - xxxxx 27 | * **ONEOPS_KEYWHIZ_KEY_STORE_PATH** - file:${SECRETS_DIR}/keywhiz_keystore.p12 28 | * **ONEOPS_KEYWHIZ_KEY_STORE_STORE_PASSWORD** - xxxxx 29 | * **ONEOPS_KEYWHIZ_KEY_STORE_KEY_PASSWORD** - xxxxx 30 | 31 | #### AD/LDAP Server Config 32 | 33 | * **ONEOPS_LDAP_SERVER** - ldap://ldap.com 34 | * **ONEOPS_LDAP_USER_BASE_DN** - dc=xxxxx,dc=xxxxx,dc=com 35 | * **ONEOPS_LDAP_USER_DN=CN** - xxxxx,DC=xxxxx,DC=xxxxx,DC=com 36 | * **ONEOPS_LDAP_PASSWORD** - xxxxx 37 | * **ONEOPS_LDAP_TRUST_STORE_PATH** - file:${SECRETS_DIR}/ldap_truststore.p12 38 | * **ONEOPS_LDAP_TRUST_STORE_STORE_PASSWORD** - xxxxx 39 | 40 | #### Keywhiz Proxy Token Auth Config 41 | 42 | * **ONEOPS_AUTH_SIGNING_KEY** - xxxxx 43 | * **ONEOPS_AUTH_EXPIRES_IN_SEC** - xxxxx 44 | 45 | #### OneOps User Datasource config 46 | 47 | * **ONEOPS_PROD_DB_URL** - jdbc:postgresql://prod-userdb:5432/xxxxx 48 | * **ONEOPS_MGMT_DB_URL** - jdbc:postgresql://mgmt-userdb:5432/xxxxx 49 | * **ONEOPS_STG_DB_URL** -jdbc:postgresql://stg-userdb:5432/xxxxx 50 | * **ONEOPS_DEV_DB_URL** -jdbc:postgresql://dev-userdb:5432/xxxxx 51 | * **ONEOPS_DB_USER** -xxxxxx 52 | * **ONEOPS_DB_PASS** -xxxxxx 53 | 54 | #### Management app config 55 | 56 | * **MANAGEMENT_USER** - xxxxx 57 | * **MANAGEMENT_PASSWORD** - xxxxx 58 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/user/tables/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.user.tables (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.user.tables

14 |
15 |

Classes

16 | 33 |
34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/endpoint/ListEndPoints.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.endpoint; 19 | 20 | import com.oneops.proxy.config.OneOpsConfig; 21 | import java.util.*; 22 | import java.util.stream.Collectors; 23 | import org.springframework.beans.factory.annotation.Value; 24 | import org.springframework.boot.actuate.endpoint.*; 25 | import org.springframework.stereotype.Component; 26 | 27 | /** 28 | * A custom actuator endpoint (/endpoints) to list all other endpoints. This includes the 29 | * custom Http Proxy endpoint ({@link com.oneops.proxy.gateway.ProxyServlet}) details also. 30 | * 31 | * @author Suresh 32 | */ 33 | @Component 34 | public class ListEndPoints extends AbstractEndpoint> { 35 | 36 | private String mgmtContext; 37 | 38 | private final List endpoints; 39 | 40 | private final OneOpsConfig config; 41 | 42 | public ListEndPoints( 43 | @Value("${management.context-path}") String mgmtContext, 44 | OneOpsConfig config, 45 | List endpoints) { 46 | super("endpoints", false, true); 47 | this.mgmtContext = mgmtContext; 48 | this.endpoints = endpoints; 49 | this.config = config; 50 | } 51 | 52 | @Override 53 | public Map invoke() { 54 | Map endPoints = 55 | endpoints 56 | .stream() 57 | .collect(Collectors.toMap(this::getEndPointID, ListEndPoints::isEnabled, (a, b) -> a)); 58 | endPoints.put(config.getProxy().getPrefix(), String.valueOf(config.getProxy().isEnabled())); 59 | return endPoints; 60 | } 61 | 62 | private String getEndPointID(Endpoint e) { 63 | return String.format("%s/%s", mgmtContext, e.getId()); 64 | } 65 | 66 | private static String isEnabled(Endpoint e) { 67 | return e.isEnabled() ? "enabled" : "disabled"; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/CreateSecretRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.common.base.Objects; 21 | import com.google.common.collect.ImmutableMap; 22 | import javax.annotation.Nullable; 23 | 24 | /** Request message to create secrets. */ 25 | public class CreateSecretRequest { 26 | @JsonProperty public final String name; 27 | 28 | @Nullable @JsonProperty public final String description; 29 | 30 | /** Base64 representation of the secret to be added. */ 31 | @JsonProperty public final String content; 32 | 33 | @Nullable @JsonProperty public final ImmutableMap metadata; 34 | 35 | /** In seconds since epoch */ 36 | @JsonProperty public final long expiry; 37 | 38 | public CreateSecretRequest( 39 | @JsonProperty("name") String name, 40 | @JsonProperty("description") @Nullable String description, 41 | @JsonProperty("content") String content, 42 | @JsonProperty("metadata") @Nullable ImmutableMap metadata, 43 | @JsonProperty("expiry") long expiry) { 44 | this.name = name; 45 | this.description = description; 46 | this.content = content; 47 | this.metadata = metadata; 48 | this.expiry = expiry; 49 | } 50 | 51 | @Override 52 | public int hashCode() { 53 | return Objects.hashCode(name, description, content, metadata, expiry); 54 | } 55 | 56 | @Override 57 | public boolean equals(Object o) { 58 | if (this == o) return true; 59 | if (o instanceof CreateSecretRequest) { 60 | CreateSecretRequest that = (CreateSecretRequest) o; 61 | if (Objects.equal(this.name, that.name) 62 | && Objects.equal(this.description, that.description) 63 | && Objects.equal(this.content, that.content) 64 | && Objects.equal(this.metadata, that.metadata) 65 | && this.expiry == that.expiry) { 66 | return true; 67 | } 68 | } 69 | return false; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/model/LoginRequest.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.model; 19 | 20 | import static com.oneops.proxy.authz.AuthDomain.PROD; 21 | 22 | import com.fasterxml.jackson.annotation.JsonProperty; 23 | import com.oneops.proxy.authz.AuthDomain; 24 | import io.swagger.annotations.ApiModelProperty; 25 | 26 | /** 27 | * Login request for user authentication. {@link ApiModelProperty} is used only for generating 28 | * swagger documentation. 29 | * 30 | * @author Suresh 31 | */ 32 | public class LoginRequest { 33 | 34 | @JsonProperty 35 | @ApiModelProperty(example = "AD Username") 36 | private String username; 37 | 38 | @JsonProperty 39 | @ApiModelProperty(example = "AD Password") 40 | private String password; 41 | 42 | @JsonProperty 43 | @ApiModelProperty(example = "prod") 44 | private AuthDomain domain = PROD; 45 | 46 | public LoginRequest() {} 47 | 48 | public LoginRequest(String username, String password, AuthDomain domain) { 49 | this.username = username; 50 | this.password = password; 51 | this.domain = domain; 52 | } 53 | 54 | public String getUsername() { 55 | return username; 56 | } 57 | 58 | public void setUsername(String username) { 59 | this.username = username; 60 | } 61 | 62 | public String getPassword() { 63 | return password; 64 | } 65 | 66 | public void setPassword(String password) { 67 | this.password = password; 68 | } 69 | 70 | public AuthDomain getDomain() { 71 | return domain; 72 | } 73 | 74 | public void setDomain(AuthDomain domain) { 75 | this.domain = domain; 76 | } 77 | 78 | @Override 79 | public String toString() { 80 | return "LoginRequest{" 81 | + "username='" 82 | + username 83 | + '\'' 84 | + ", password=******" 85 | + ", domain='" 86 | + domain.getType() 87 | + '\'' 88 | + '}'; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/generated/java/com/oneops/user/tables/records/SchemaMigrationsRecord.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package com.oneops.user.tables.records; 5 | 6 | import com.oneops.user.tables.SchemaMigrations; 7 | import org.jooq.*; 8 | import org.jooq.impl.TableRecordImpl; 9 | 10 | import javax.annotation.Generated; 11 | 12 | /** This class is generated by jOOQ. */ 13 | @Generated( 14 | value = {"http://www.jooq.org", "jOOQ version:3.9.2"}, 15 | comments = "This class is generated by jOOQ" 16 | ) 17 | @SuppressWarnings({"all", "unchecked", "rawtypes"}) 18 | public class SchemaMigrationsRecord extends TableRecordImpl 19 | implements Record1 { 20 | 21 | private static final long serialVersionUID = 1522703260; 22 | 23 | /** Setter for public.schema_migrations.version. */ 24 | public void setVersion(String value) { 25 | set(0, value); 26 | } 27 | 28 | /** Getter for public.schema_migrations.version. */ 29 | public String getVersion() { 30 | return (String) get(0); 31 | } 32 | 33 | // ------------------------------------------------------------------------- 34 | // Record1 type implementation 35 | // ------------------------------------------------------------------------- 36 | 37 | /** {@inheritDoc} */ 38 | @Override 39 | public Row1 fieldsRow() { 40 | return (Row1) super.fieldsRow(); 41 | } 42 | 43 | /** {@inheritDoc} */ 44 | @Override 45 | public Row1 valuesRow() { 46 | return (Row1) super.valuesRow(); 47 | } 48 | 49 | /** {@inheritDoc} */ 50 | @Override 51 | public Field field1() { 52 | return SchemaMigrations.SCHEMA_MIGRATIONS.VERSION; 53 | } 54 | 55 | /** {@inheritDoc} */ 56 | @Override 57 | public String value1() { 58 | return getVersion(); 59 | } 60 | 61 | /** {@inheritDoc} */ 62 | @Override 63 | public SchemaMigrationsRecord value1(String value) { 64 | setVersion(value); 65 | return this; 66 | } 67 | 68 | /** {@inheritDoc} */ 69 | @Override 70 | public SchemaMigrationsRecord values(String value1) { 71 | value1(value1); 72 | return this; 73 | } 74 | 75 | // ------------------------------------------------------------------------- 76 | // Constructors 77 | // ------------------------------------------------------------------------- 78 | 79 | /** Create a detached SchemaMigrationsRecord */ 80 | public SchemaMigrationsRecord() { 81 | super(SchemaMigrations.SCHEMA_MIGRATIONS); 82 | } 83 | 84 | /** Create a detached, initialised SchemaMigrationsRecord */ 85 | public SchemaMigrationsRecord(String version) { 86 | super(SchemaMigrations.SCHEMA_MIGRATIONS); 87 | 88 | set(0, version); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/metrics/MetricsUtilService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.metrics; 19 | 20 | import static java.lang.String.format; 21 | import static java.lang.System.currentTimeMillis; 22 | 23 | import org.springframework.boot.actuate.metrics.dropwizard.DropwizardMetricServices; 24 | import org.springframework.stereotype.Service; 25 | 26 | /** 27 | * Some utility functions for timer and size. 28 | * 29 | * @author Suresh G 30 | */ 31 | @Service 32 | public class MetricsUtilService { 33 | 34 | private DropwizardMetricServices metricService; 35 | 36 | public MetricsUtilService(DropwizardMetricServices metricService) { 37 | this.metricService = metricService; 38 | } 39 | 40 | /** A helper method to time operations or errors. */ 41 | public T time(String metric, ThrowingSupplier lambda) throws E { 42 | long start = currentTimeMillis(); 43 | try { 44 | return lambda.get(); 45 | } catch (Exception ex) { 46 | metricService.increment("meter." + metric + ".err"); 47 | throw ex; 48 | } finally { 49 | metricService.submit("timer." + metric, currentTimeMillis() - start); 50 | } 51 | } 52 | 53 | /** 54 | * Converts a given number to a string preceded by the corresponding binary International System 55 | * of Units (SI) prefix. 56 | */ 57 | public static String binaryPrefix(long size) { 58 | long unit = 1000; 59 | String suffix = "B"; 60 | 61 | if (size < unit) { 62 | return format("%d %s", size, suffix); 63 | } else { 64 | String prefix = "KMGTPEZY"; 65 | int exp = (int) (Math.log(size) / Math.log(unit)); 66 | // Binary Prefix mnemonic that is prepended to the units. 67 | String binPrefix = prefix.charAt(exp - 1) + suffix; 68 | // Count => (unit^0.x * unit^exp)/unit^exp 69 | return format("%.2f %s", size / Math.pow(unit, exp), binPrefix); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/config/AccessLogFilter.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.config; 19 | 20 | import static ch.qos.logback.core.spi.FilterReply.NEUTRAL; 21 | import static java.util.Arrays.asList; 22 | import static java.util.Collections.emptyList; 23 | 24 | import ch.qos.logback.access.spi.AccessEvent; 25 | import ch.qos.logback.core.filter.AbstractMatcherFilter; 26 | import ch.qos.logback.core.spi.FilterReply; 27 | import java.util.List; 28 | 29 | /** 30 | * A simple access filter to remove the management health calls (/health). We could have used 31 | * {@link ch.qos.logback.access.boolex.JaninoEventEvaluator}, but require additional dependencies 32 | * and our use case is simple. The filter along with ignorePaths is configured in 33 | * logback-access.xml. 34 | * 35 | * @author Suresh 36 | * @see 37 | */ 38 | public class AccessLogFilter extends AbstractMatcherFilter { 39 | 40 | /** Comma separated request paths, to be ignored from logging into access log. */ 41 | private String ignorePaths; 42 | 43 | private List paths; 44 | 45 | public void start() { 46 | if (this.ignorePaths != null) { 47 | super.start(); 48 | } 49 | } 50 | 51 | public String getIgnorePaths() { 52 | return ignorePaths; 53 | } 54 | 55 | public void setIgnorePaths(String ignorePaths) { 56 | this.ignorePaths = ignorePaths; 57 | if (ignorePaths == null) { 58 | paths = emptyList(); 59 | } else { 60 | paths = asList(this.ignorePaths.split(",")); 61 | } 62 | } 63 | 64 | @Override 65 | public FilterReply decide(AccessEvent event) { 66 | if (!isStarted()) { 67 | return NEUTRAL; 68 | } 69 | 70 | if (paths.stream().anyMatch(path -> event.getRequestURI().matches(path))) { 71 | return onMatch; 72 | } else { 73 | return onMismatch; 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/AutomationSecretResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | import static com.oneops.proxy.keywhiz.model.Secret.decodedLength; 21 | 22 | import com.fasterxml.jackson.annotation.*; 23 | import com.google.auto.value.AutoValue; 24 | import com.google.common.collect.*; 25 | import java.util.Map; 26 | 27 | /** 28 | * JSON Serialization class for a REST response {@link Secret}. 29 | * 30 | *

Automation View, does not include secret contents. 31 | */ 32 | @AutoValue 33 | public abstract class AutomationSecretResponse { 34 | 35 | public static AutomationSecretResponse create( 36 | long id, 37 | String name, 38 | String secret, 39 | ApiDate creationDate, 40 | ImmutableMap metadata, 41 | ImmutableList groups, 42 | long expiry) { 43 | return new AutoValue_AutomationSecretResponse( 44 | id, name, secret, decodedLength(secret), creationDate, groups, metadata, expiry); 45 | } 46 | 47 | public static AutomationSecretResponse fromSecret(Secret secret, ImmutableList groups) { 48 | checkNotNull(secret); 49 | return AutomationSecretResponse.create( 50 | secret.getId(), 51 | secret.getDisplayName(), 52 | secret.getSecret(), 53 | secret.getCreatedAt(), 54 | secret.getMetadata(), 55 | groups, 56 | secret.getExpiry()); 57 | } 58 | 59 | @JsonProperty("id") 60 | public abstract long id(); 61 | 62 | @JsonProperty("name") 63 | public abstract String name(); 64 | 65 | @JsonProperty("secret") 66 | public abstract String secret(); 67 | 68 | @JsonProperty("secretLength") 69 | public abstract long secretLength(); 70 | 71 | @JsonProperty("creationDate") 72 | public abstract ApiDate creationDate(); 73 | 74 | @JsonProperty("groups") 75 | public abstract ImmutableList groups(); 76 | 77 | @JsonAnyGetter 78 | @JsonProperty("metadata") 79 | public abstract Map metadata(); 80 | 81 | @JsonProperty("expiry") 82 | public abstract long expiry(); 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/audit/Event.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.audit; 19 | 20 | import java.util.Map; 21 | 22 | /** 23 | * An audit event for secrets-proxy. 24 | * 25 | *

Eg: SECRET_CREATE | User: suresh | Group: oneops_keywhiz-proxy_prod | Object: 26 | * prod_db_password.txt | ExtraInfo: 27 | * 28 | * @author Suresh 29 | */ 30 | public class Event { 31 | 32 | /** Event type */ 33 | private final EventTag type; 34 | /** User generated the event. */ 35 | private final String user; 36 | /** Application group of event. */ 37 | private final String appGroup; 38 | /** The name of the affected object */ 39 | private final String objectName; 40 | 41 | /** Any extra information */ 42 | private final Map extraInfo; 43 | 44 | public Event( 45 | EventTag type, 46 | String user, 47 | String appGroup, 48 | String objectName, 49 | Map extraInfo) { 50 | this.type = type; 51 | this.user = user; 52 | this.appGroup = appGroup; 53 | this.objectName = objectName; 54 | this.extraInfo = extraInfo; 55 | } 56 | 57 | public Event(EventTag type, String user, String appGroup) { 58 | this(type, user, appGroup, "", null); 59 | } 60 | 61 | public Event(EventTag type, String user, String appGroup, String objectName) { 62 | this(type, user, appGroup, objectName, null); 63 | } 64 | 65 | public EventTag getType() { 66 | return type; 67 | } 68 | 69 | public String getUser() { 70 | return user; 71 | } 72 | 73 | public String getAppGroup() { 74 | return appGroup; 75 | } 76 | 77 | public String getObjectName() { 78 | return objectName; 79 | } 80 | 81 | public Map getExtraInfo() { 82 | return extraInfo; 83 | } 84 | 85 | @Override 86 | public String toString() { 87 | String extInfo = extraInfo == null ? "" : extraInfo.toString(); 88 | return String.format( 89 | "%-25s | User: %-15s | Group: %-45s | Object: %-30s | ExtraInfo: %s ", 90 | type, user, appGroup, objectName, extInfo); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/generated/java/com/oneops/user/Tables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * This file is generated by jOOQ. 3 | */ 4 | package com.oneops.user; 5 | 6 | import com.oneops.user.tables.*; 7 | 8 | import javax.annotation.Generated; 9 | 10 | /** Convenience access to all tables in public */ 11 | @Generated( 12 | value = {"http://www.jooq.org", "jOOQ version:3.9.2"}, 13 | comments = "This class is generated by jOOQ" 14 | ) 15 | @SuppressWarnings({"all", "unchecked", "rawtypes"}) 16 | public class Tables { 17 | 18 | /** The table public.authentications. */ 19 | public static final Authentications AUTHENTICATIONS = 20 | com.oneops.user.tables.Authentications.AUTHENTICATIONS; 21 | 22 | /** The table public.ci_proxies. */ 23 | public static final CiProxies CI_PROXIES = com.oneops.user.tables.CiProxies.CI_PROXIES; 24 | 25 | /** The table public.ci_proxies_teams. */ 26 | public static final CiProxiesTeams CI_PROXIES_TEAMS = 27 | com.oneops.user.tables.CiProxiesTeams.CI_PROXIES_TEAMS; 28 | 29 | /** The table public.group_members. */ 30 | public static final GroupMembers GROUP_MEMBERS = 31 | com.oneops.user.tables.GroupMembers.GROUP_MEMBERS; 32 | 33 | /** The table public.groups. */ 34 | public static final Groups GROUPS = com.oneops.user.tables.Groups.GROUPS; 35 | 36 | /** The table public.groups_teams. */ 37 | public static final GroupsTeams GROUPS_TEAMS = com.oneops.user.tables.GroupsTeams.GROUPS_TEAMS; 38 | 39 | /** The table public.invitations. */ 40 | public static final Invitations INVITATIONS = com.oneops.user.tables.Invitations.INVITATIONS; 41 | 42 | /** The table public.misc_docs. */ 43 | public static final MiscDocs MISC_DOCS = com.oneops.user.tables.MiscDocs.MISC_DOCS; 44 | 45 | /** The table public.organizations. */ 46 | public static final Organizations ORGANIZATIONS = 47 | com.oneops.user.tables.Organizations.ORGANIZATIONS; 48 | 49 | /** The table public.schema_migrations. */ 50 | public static final SchemaMigrations SCHEMA_MIGRATIONS = 51 | com.oneops.user.tables.SchemaMigrations.SCHEMA_MIGRATIONS; 52 | 53 | /** The table public.teams. */ 54 | public static final Teams TEAMS = com.oneops.user.tables.Teams.TEAMS; 55 | 56 | /** The table public.teams_users. */ 57 | public static final TeamsUsers TEAMS_USERS = com.oneops.user.tables.TeamsUsers.TEAMS_USERS; 58 | 59 | /** The table public.user_favorites. */ 60 | public static final UserFavorites USER_FAVORITES = 61 | com.oneops.user.tables.UserFavorites.USER_FAVORITES; 62 | 63 | /** The table public.user_watches. */ 64 | public static final UserWatches USER_WATCHES = com.oneops.user.tables.UserWatches.USER_WATCHES; 65 | 66 | /** The table public.users. */ 67 | public static final Users USERS = com.oneops.user.tables.Users.USERS; 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/SecretSeries.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import static com.google.common.base.Strings.nullToEmpty; 20 | 21 | import com.google.auto.value.AutoValue; 22 | import com.google.common.collect.ImmutableMap; 23 | import java.util.*; 24 | import javax.annotation.Nullable; 25 | 26 | /** 27 | * Maps to entity from secrets table. A secret may have many versions, each with different content, 28 | * but the versions share common information in a SecretSeries, such as name, description, and 29 | * metadata. In particular, access control is granted to a SecretSeries and not a specific version 30 | * in that series. New secret versions in the series will "inherit" the same group associations. 31 | * One-to-many mapping to {@link SecretContent}s. 32 | */ 33 | @AutoValue 34 | public abstract class SecretSeries { 35 | 36 | public static SecretSeries of( 37 | long id, 38 | String name, 39 | @Nullable String description, 40 | ApiDate createdAt, 41 | @Nullable String createdBy, 42 | ApiDate updatedAt, 43 | @Nullable String updatedBy, 44 | @Nullable String type, 45 | @Nullable Map generationOptions, 46 | @Nullable Long currentVersion) { 47 | 48 | ImmutableMap options = 49 | (generationOptions == null) ? ImmutableMap.of() : ImmutableMap.copyOf(generationOptions); 50 | 51 | return new AutoValue_SecretSeries( 52 | id, 53 | name, 54 | nullToEmpty(description), 55 | createdAt, 56 | nullToEmpty(createdBy), 57 | updatedAt, 58 | nullToEmpty(updatedBy), 59 | Optional.ofNullable(type), 60 | options, 61 | Optional.ofNullable(currentVersion)); 62 | } 63 | 64 | public abstract long id(); 65 | 66 | public abstract String name(); 67 | 68 | public abstract String description(); 69 | 70 | public abstract ApiDate createdAt(); 71 | 72 | public abstract String createdBy(); 73 | 74 | public abstract ApiDate updatedAt(); 75 | 76 | public abstract String updatedBy(); 77 | 78 | public abstract Optional type(); 79 | 80 | public abstract ImmutableMap generationOptions(); 81 | 82 | public abstract Optional currentVersion(); 83 | } 84 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/user/tables/records/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.user.tables.records (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.user.tables.records

14 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/web/support/AppGroupArgResolver.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.web.support; 19 | 20 | import static com.oneops.proxy.model.AppGroup.APP_NAME_PARAM; 21 | import static org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST; 22 | import static org.springframework.web.servlet.HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; 23 | 24 | import com.oneops.proxy.auth.user.OneOpsUser; 25 | import com.oneops.proxy.config.WebConfig; 26 | import com.oneops.proxy.model.AppGroup; 27 | import java.util.*; 28 | import org.springframework.core.MethodParameter; 29 | import org.springframework.security.core.Authentication; 30 | import org.springframework.web.bind.support.WebDataBinderFactory; 31 | import org.springframework.web.context.request.NativeWebRequest; 32 | import org.springframework.web.method.support.*; 33 | 34 | /** 35 | * {@link AppGroup} method argument resolver for rest controllers. It's configured in {@link 36 | * WebConfig#addArgumentResolvers(List)}. 37 | * 38 | * @author Suresh G 39 | */ 40 | public class AppGroupArgResolver implements HandlerMethodArgumentResolver { 41 | 42 | @Override 43 | public boolean supportsParameter(MethodParameter param) { 44 | return param.getParameterType().equals(AppGroup.class); 45 | } 46 | 47 | /** 48 | * Construct new {@link AppGroup} object from the given Web request. The authenticated user is 49 | * available in the web request principal. 50 | */ 51 | @Override 52 | public AppGroup resolveArgument( 53 | MethodParameter parameter, 54 | ModelAndViewContainer mavContainer, 55 | NativeWebRequest webReq, 56 | WebDataBinderFactory binderFactory) 57 | throws Exception { 58 | Authentication auth = (Authentication) webReq.getUserPrincipal(); 59 | OneOpsUser user = (OneOpsUser) auth.getPrincipal(); 60 | 61 | // Get the path variable. 62 | @SuppressWarnings("unchecked") 63 | Map pathVars = 64 | (Map) webReq.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, SCOPE_REQUEST); 65 | String group = pathVars != null ? pathVars.get(APP_NAME_PARAM) : ""; 66 | return AppGroup.from(user.getDomain(), group); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /docs/javadocs/com/oneops/proxy/config/package-frame.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | com.oneops.proxy.config (OneOps Secrets Proxy 1.2.1-SNAPSHOT API) 8 | 9 | 10 | 11 | 12 | 13 |

com.oneops.proxy.config

14 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/SecretContent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import static com.google.common.base.Strings.nullToEmpty; 20 | 21 | import com.fasterxml.jackson.annotation.JsonAnyGetter; 22 | import com.google.auto.value.AutoValue; 23 | import com.google.common.base.MoreObjects; 24 | import com.google.common.collect.ImmutableMap; 25 | import javax.annotation.Nullable; 26 | 27 | /** 28 | * Maps to entity from secrets_content table. Contains content and related information on a specific 29 | * version of a secret. Many-to-one mapping with a {@link SecretSeries}. 30 | */ 31 | @AutoValue 32 | public abstract class SecretContent { 33 | 34 | public static SecretContent of( 35 | long id, 36 | long secretSeriesId, 37 | String encryptedContent, 38 | String hmac, 39 | ApiDate createdAt, 40 | @Nullable String createdBy, 41 | ApiDate updatedAt, 42 | @Nullable String updatedBy, 43 | ImmutableMap metadata, 44 | long expiry) { 45 | 46 | return new AutoValue_SecretContent( 47 | id, 48 | secretSeriesId, 49 | encryptedContent, 50 | hmac, 51 | createdAt, 52 | nullToEmpty(createdBy), 53 | updatedAt, 54 | nullToEmpty(updatedBy), 55 | metadata, 56 | expiry); 57 | } 58 | 59 | public abstract long id(); 60 | 61 | public abstract long secretSeriesId(); 62 | 63 | public abstract String encryptedContent(); 64 | 65 | public abstract String hmac(); 66 | 67 | public abstract ApiDate createdAt(); 68 | 69 | public abstract String createdBy(); 70 | 71 | public abstract ApiDate updatedAt(); 72 | 73 | public abstract String updatedBy(); 74 | 75 | @JsonAnyGetter 76 | public abstract ImmutableMap metadata(); 77 | 78 | public abstract long expiry(); 79 | 80 | @Override 81 | public String toString() { 82 | return MoreObjects.toStringHelper(this) 83 | .add("id", id()) 84 | .add("secretSeriesId", secretSeriesId()) 85 | .add("encryptedContent", "[REDACTED]") 86 | .add("checksum", hmac()) 87 | .add("createdAt", createdAt()) 88 | .add("createdBy", createdBy()) 89 | .add("updatedAt", updatedAt()) 90 | .add("updatedBy", updatedBy()) 91 | .add("metadata", metadata()) 92 | .add("expiry", expiry()) 93 | .omitNullValues() 94 | .toString(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/http/XsrfTokenInterceptor.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.keywhiz.http; 19 | 20 | import static com.oneops.proxy.keywhiz.http.CookieCutter.decodeCookies; 21 | 22 | import com.google.common.net.HttpHeaders; 23 | import java.io.IOException; 24 | import okhttp3.*; 25 | import org.slf4j.*; 26 | 27 | /** 28 | * Http request interceptor to handle server-side XSRF protection. If the server set a cookie with a 29 | * specified name, the client will send a header with each request with a specified name and value 30 | * of the server-supplied cookie. 31 | * 32 | * @author Suresh 33 | * @see Cookie-to-Header 35 | * Token, an anti-CSRF technique. 36 | */ 37 | public class XsrfTokenInterceptor implements Interceptor { 38 | 39 | private static final Logger log = LoggerFactory.getLogger(XsrfTokenInterceptor.class); 40 | 41 | private String xsrfCookieName = "XSRF-TOKEN"; 42 | private String xsrfHeaderName = "X-XSRF-TOKEN"; 43 | 44 | public XsrfTokenInterceptor() {} 45 | 46 | public XsrfTokenInterceptor(String xsrfCookieName, String xsrfHeaderName) { 47 | this.xsrfCookieName = xsrfCookieName; 48 | this.xsrfHeaderName = xsrfHeaderName; 49 | } 50 | 51 | @Override 52 | public Response intercept(Chain chain) throws IOException { 53 | Request req = chain.request(); 54 | try { 55 | for (String header : req.headers(HttpHeaders.COOKIE)) { 56 | for (Cookie cookie : decodeCookies(header, req.url().host())) { 57 | if (cookie.name().equalsIgnoreCase(xsrfCookieName)) { 58 | if (log.isDebugEnabled()) { 59 | log.debug(String.format("Setting XSRF token header: %s to request.", xsrfHeaderName)); 60 | } 61 | req = req.newBuilder().addHeader(xsrfHeaderName, cookie.value()).build(); 62 | } 63 | } 64 | } 65 | } catch (Exception ex) { 66 | log.warn("Error setting " + xsrfHeaderName + " header in request", ex); 67 | } 68 | return chain.proceed(req); 69 | } 70 | 71 | public String getXsrfCookieName() { 72 | return xsrfCookieName; 73 | } 74 | 75 | public String getXsrfHeaderName() { 76 | return xsrfHeaderName; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/ClientDetailResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.common.collect.ImmutableList; 21 | import javax.annotation.Nullable; 22 | 23 | public class ClientDetailResponse { 24 | 25 | @JsonProperty public final long id; 26 | 27 | @JsonProperty public final String name; 28 | 29 | @JsonProperty public final String description; 30 | 31 | @JsonProperty public final ApiDate creationDate; 32 | 33 | @JsonProperty public final ApiDate updateDate; 34 | 35 | @JsonProperty public final String createdBy; 36 | 37 | @JsonProperty public final String updatedBy; 38 | 39 | @JsonProperty public final ApiDate lastSeen; 40 | 41 | /** List of secrets the group has access to. The secrets do not contain content. */ 42 | @JsonProperty public final ImmutableList secrets; 43 | 44 | @JsonProperty public final ImmutableList groups; 45 | 46 | public ClientDetailResponse( 47 | @JsonProperty("id") long id, 48 | @JsonProperty("name") String name, 49 | @JsonProperty("description") String description, 50 | @JsonProperty("creationDate") ApiDate creationDate, 51 | @JsonProperty("updateDate") ApiDate updateDate, 52 | @JsonProperty("createdBy") String createdBy, 53 | @JsonProperty("updatedBy") String updatedBy, 54 | @JsonProperty("lastSeen") @Nullable ApiDate lastSeen, 55 | @JsonProperty("groups") ImmutableList groups, 56 | @JsonProperty("secrets") ImmutableList secrets) { 57 | this.id = id; 58 | this.name = name; 59 | this.description = description; 60 | this.creationDate = creationDate; 61 | this.updateDate = updateDate; 62 | this.createdBy = createdBy; 63 | this.updatedBy = updatedBy; 64 | this.lastSeen = lastSeen; 65 | this.groups = groups; 66 | this.secrets = secrets; 67 | } 68 | 69 | public static ClientDetailResponse fromClient( 70 | Client client, ImmutableList groups, ImmutableList secrets) { 71 | return new ClientDetailResponse( 72 | client.getId(), 73 | client.getName(), 74 | client.getDescription(), 75 | client.getCreatedAt(), 76 | client.getUpdatedAt(), 77 | client.getCreatedBy(), 78 | client.getUpdatedBy(), 79 | client.getLastSeen(), 80 | groups, 81 | secrets); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/config/WebConfig.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.config; 19 | 20 | import static org.springframework.http.MediaType.*; 21 | 22 | import com.oneops.proxy.model.AppGroup; 23 | import com.oneops.proxy.web.support.*; 24 | import java.util.List; 25 | import org.slf4j.*; 26 | import org.springframework.context.annotation.Configuration; 27 | import org.springframework.web.method.support.HandlerMethodArgumentResolver; 28 | import org.springframework.web.servlet.config.annotation.*; 29 | 30 | /** 31 | * ContentNegotiation configuration for the application. 32 | * 33 | *

Note: If you add ({@link EnableWebMvc}) annotation, you switch off everything in spring boot. 34 | * 35 | * @author Suresh 36 | */ 37 | @Configuration 38 | // @EnableWebMvc 39 | public class WebConfig extends WebMvcConfigurerAdapter { 40 | 41 | private final Logger log = LoggerFactory.getLogger(getClass()); 42 | 43 | @Override 44 | public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { 45 | log.info("Configuring ContentNegotiation for the application."); 46 | configurer 47 | .favorPathExtension(false) 48 | .favorParameter(true) 49 | .parameterName("mediaType") 50 | .ignoreAcceptHeader(true) 51 | .useJaf(false) 52 | .defaultContentType(APPLICATION_JSON_UTF8) 53 | .mediaType("xml", APPLICATION_XML) 54 | .mediaType("json", APPLICATION_JSON_UTF8); 55 | } 56 | 57 | /** 58 | * Turn on path variable suffix pattern matching ONLY for suffixes you explicitly register using 59 | * {@link #configureContentNegotiation(ContentNegotiationConfigurer)}. 60 | */ 61 | @Override 62 | public void configurePathMatch(PathMatchConfigurer matcher) { 63 | log.info("Configuring Suffix PathMatching for the application."); 64 | matcher.setUseSuffixPatternMatch(false); 65 | // matcher.setUseRegisteredSuffixPatternMatch(false); 66 | } 67 | 68 | /** {@link AppGroup} argument resolver used in Rest controllers. */ 69 | @Override 70 | public void addArgumentResolvers(List argResolvers) { 71 | log.info("Configuring AppGroup arg resolver for the application."); 72 | argResolvers.add(new AppGroupArgResolver()); 73 | argResolvers.add(new AppSecretArgResolver()); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/ApiDate.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import static java.lang.String.format; 20 | 21 | import com.fasterxml.jackson.core.*; 22 | import com.fasterxml.jackson.databind.*; 23 | import com.fasterxml.jackson.databind.annotation.*; 24 | import java.io.IOException; 25 | import java.time.*; 26 | import java.time.format.DateTimeFormatter; 27 | 28 | /** 29 | * This is a wrapper for the date class used in API responses so we can have a custom JSON 30 | * serializer and deserializer. 31 | */ 32 | @JsonSerialize(using = ApiDate.ApiDateSerializer.class) 33 | @JsonDeserialize(using = ApiDate.ApiDateDeserializer.class) 34 | public class ApiDate { 35 | 36 | private long epochSecond; 37 | 38 | public long toEpochSecond() { 39 | return epochSecond; 40 | } 41 | 42 | public ApiDate(long epochSecond) { 43 | this.epochSecond = epochSecond; 44 | } 45 | 46 | public static ApiDate parse(String s) { 47 | OffsetDateTime odt = OffsetDateTime.parse(s); 48 | return new ApiDate(odt.toEpochSecond()); 49 | } 50 | 51 | public static ApiDate now() { 52 | return new ApiDate(OffsetDateTime.now().toEpochSecond()); 53 | } 54 | 55 | @Override 56 | public String toString() { 57 | return format("ApiDate[%d]", epochSecond); 58 | } 59 | 60 | @Override 61 | public boolean equals(Object obj) { 62 | if (obj instanceof ApiDate) { 63 | ApiDate that = (ApiDate) obj; 64 | return this.epochSecond == that.epochSecond; 65 | } 66 | return false; 67 | } 68 | 69 | @Override 70 | public int hashCode() { 71 | return Long.hashCode(this.epochSecond); 72 | } 73 | 74 | static class ApiDateSerializer extends JsonSerializer { 75 | private static DateTimeFormatter formatter = 76 | DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); 77 | 78 | @Override 79 | public void serialize(ApiDate value, JsonGenerator gen, SerializerProvider serializers) 80 | throws IOException { 81 | Instant i = Instant.ofEpochSecond(value.epochSecond); 82 | gen.writeString(formatter.format(i.atOffset(ZoneOffset.UTC))); 83 | } 84 | } 85 | 86 | static class ApiDateDeserializer extends JsonDeserializer { 87 | @Override 88 | public ApiDate deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException { 89 | OffsetDateTime odt = parser.readValueAs(OffsetDateTime.class); 90 | return new ApiDate(odt.toEpochSecond()); 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/auth/login/LoginAuthToken.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.auth.login; 19 | 20 | import java.util.Collection; 21 | import org.springframework.security.authentication.AbstractAuthenticationToken; 22 | import org.springframework.security.core.*; 23 | 24 | /** 25 | * An {@link Authentication} object for identifying login token in {@link LoginProcessingFilter}. 26 | * 27 | * @author Suresh 28 | */ 29 | public class LoginAuthToken extends AbstractAuthenticationToken { 30 | 31 | private final Object principal; 32 | 33 | private Object credentials; 34 | 35 | /** 36 | * This constructor can be safely used by any code that wishes to create a LoginAuthToken 37 | * , as the {@link #isAuthenticated()} will return false. 38 | */ 39 | public LoginAuthToken(Object principal, Object credentials) { 40 | super(null); 41 | this.principal = principal; 42 | this.credentials = credentials; 43 | setAuthenticated(false); 44 | } 45 | 46 | /** 47 | * This constructor should only be used by AuthenticationManager or 48 | * AuthenticationProvider implementations that are satisfied with producing a trusted (i.e. 49 | * {@link #isAuthenticated()} = true) authentication token. 50 | * 51 | * @param principal 52 | * @param credentials 53 | * @param authorities 54 | */ 55 | public LoginAuthToken( 56 | Object principal, Object credentials, Collection authorities) { 57 | super(authorities); 58 | this.principal = principal; 59 | this.credentials = credentials; 60 | super.setAuthenticated(true); // must use super, as we override 61 | } 62 | 63 | public Object getCredentials() { 64 | return this.credentials; 65 | } 66 | 67 | public Object getPrincipal() { 68 | return this.principal; 69 | } 70 | 71 | public void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException { 72 | if (isAuthenticated) { 73 | throw new IllegalArgumentException( 74 | "Cannot set this token to trusted - use constructor which takes a GrantedAuthority list instead"); 75 | } 76 | super.setAuthenticated(false); 77 | } 78 | 79 | @Override 80 | public void eraseCredentials() { 81 | super.eraseCredentials(); 82 | credentials = null; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/auth/user/LdapUserDetailsService.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.auth.user; 19 | 20 | import static com.oneops.proxy.auth.user.OneOpsUser.Role.USER; 21 | import static java.util.Collections.singletonList; 22 | 23 | import com.oneops.proxy.authz.AuthDomain; 24 | import com.oneops.proxy.ldap.LdapClient; 25 | import java.io.IOException; 26 | import java.util.List; 27 | import org.ldaptive.LdapException; 28 | import org.slf4j.Logger; 29 | import org.slf4j.LoggerFactory; 30 | import org.springframework.security.authentication.AuthenticationProvider; 31 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 32 | import org.springframework.security.core.userdetails.UserDetails; 33 | import org.springframework.security.core.userdetails.UserDetailsService; 34 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 35 | import sun.security.x509.X500Name; 36 | 37 | /** 38 | * For loading OneOps user-specific data from database or LDAP. This is used by the default {@link 39 | * AuthenticationProvider} to get the {@link UserDetails}. 40 | * 41 | *

Note: This service is created during the initial phase of development and is not used anywhere 42 | * in the authentication process. 43 | * 44 | * @author Suresh 45 | */ 46 | // @Service 47 | public class LdapUserDetailsService implements UserDetailsService { 48 | 49 | private final Logger log = LoggerFactory.getLogger(getClass()); 50 | 51 | private LdapClient ldapClient; 52 | 53 | public LdapUserDetailsService(LdapClient ldapClient) { 54 | this.ldapClient = ldapClient; 55 | } 56 | 57 | @Override 58 | public OneOpsUser loadUserByUsername(String username) throws UsernameNotFoundException { 59 | try { 60 | List x500Names = ldapClient.searchUser(username); 61 | if (x500Names.size() == 0) { 62 | throw new UsernameNotFoundException("Can't load the user details for " + username); 63 | } 64 | X500Name x500Name = x500Names.get(0); 65 | List authorities = 66 | singletonList(new SimpleGrantedAuthority(USER.authority())); 67 | return new OneOpsUser(username, null, authorities, x500Name.getCommonName(), AuthDomain.PROD); 68 | 69 | } catch (IOException | LdapException e) { 70 | throw new UsernameNotFoundException("Can't load the user details for " + username, e); 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/web/support/AppSecretArgResolver.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.web.support; 19 | 20 | import static com.oneops.proxy.model.AppGroup.APP_NAME_PARAM; 21 | import static com.oneops.proxy.model.AppSecret.APP_SECRET_PARAM; 22 | import static org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST; 23 | import static org.springframework.web.servlet.HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE; 24 | 25 | import com.oneops.proxy.auth.user.OneOpsUser; 26 | import com.oneops.proxy.config.WebConfig; 27 | import com.oneops.proxy.model.*; 28 | import java.util.*; 29 | import org.springframework.core.MethodParameter; 30 | import org.springframework.security.core.Authentication; 31 | import org.springframework.web.bind.support.WebDataBinderFactory; 32 | import org.springframework.web.context.request.NativeWebRequest; 33 | import org.springframework.web.method.support.*; 34 | 35 | /** 36 | * {@link AppSecret} method argument resolver for rest controllers. It's configured in {@link 37 | * WebConfig#addArgumentResolvers(List)}. 38 | * 39 | * @author Suresh G 40 | */ 41 | public class AppSecretArgResolver implements HandlerMethodArgumentResolver { 42 | 43 | @Override 44 | public boolean supportsParameter(MethodParameter param) { 45 | return param.getParameterType().equals(AppSecret.class); 46 | } 47 | 48 | /** 49 | * Construct new {@link AppSecret} object from the given Web request. The authenticated user is 50 | * available in the web request principal. 51 | */ 52 | @Override 53 | public Object resolveArgument( 54 | MethodParameter parameter, 55 | ModelAndViewContainer mavContainer, 56 | NativeWebRequest webReq, 57 | WebDataBinderFactory binderFactory) 58 | throws Exception { 59 | Authentication auth = (Authentication) webReq.getUserPrincipal(); 60 | OneOpsUser user = (OneOpsUser) auth.getPrincipal(); 61 | 62 | // Get the path variable. 63 | @SuppressWarnings("unchecked") 64 | Map pathVars = 65 | (Map) webReq.getAttribute(URI_TEMPLATE_VARIABLES_ATTRIBUTE, SCOPE_REQUEST); 66 | String group = pathVars != null ? pathVars.get(APP_NAME_PARAM) : ""; 67 | String secret = pathVars != null ? pathVars.get(APP_SECRET_PARAM) : ""; 68 | 69 | AppGroup appGroup = new AppGroup(user.getDomain(), group); 70 | return new AppSecret(secret, appGroup); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/SanitizedSecretWithGroups.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2015 Square, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package com.oneops.proxy.keywhiz.model; 18 | 19 | import static com.google.common.base.Preconditions.checkNotNull; 20 | 21 | import com.fasterxml.jackson.annotation.*; 22 | import com.google.auto.value.AutoValue; 23 | import java.util.List; 24 | 25 | /** {@link Secret} object, but without the secret content and with group metadata. */ 26 | @AutoValue 27 | public abstract class SanitizedSecretWithGroups { 28 | 29 | @JsonCreator 30 | public static SanitizedSecretWithGroups of( 31 | @JsonProperty("secret") SanitizedSecret secret, @JsonProperty("groups") List groups) { 32 | return new AutoValue_SanitizedSecretWithGroups(secret, groups); 33 | } 34 | 35 | public static SanitizedSecretWithGroups of(long id, String name, List groups) { 36 | SanitizedSecret sanitizedSecret = 37 | SanitizedSecret.of( 38 | id, 39 | name, 40 | null, 41 | "", 42 | new ApiDate(0), 43 | null, 44 | new ApiDate(0), 45 | null, 46 | null, 47 | null, 48 | null, 49 | 0, 50 | null); 51 | return SanitizedSecretWithGroups.of(sanitizedSecret, groups); 52 | } 53 | 54 | public static SanitizedSecretWithGroups fromSecretSeriesAndContentAndGroups( 55 | SecretSeriesAndContent seriesAndContent, List groups) { 56 | SanitizedSecret sanitizedSecret = SanitizedSecret.fromSecretSeriesAndContent(seriesAndContent); 57 | return SanitizedSecretWithGroups.of(sanitizedSecret, groups); 58 | } 59 | 60 | /** 61 | * Build a matching representation of a secret, but without sensitive content. 62 | * 63 | * @param secret secret model to build from 64 | * @param groups the list of groups 65 | * @return content of secret model, but without sensitive content 66 | */ 67 | public static SanitizedSecretWithGroups fromSecret(Secret secret, List groups) { 68 | checkNotNull(secret); 69 | SanitizedSecret sanitizedSecret = SanitizedSecret.fromSecret(secret); 70 | return SanitizedSecretWithGroups.of(sanitizedSecret, groups); 71 | } 72 | 73 | @JsonProperty 74 | public abstract SanitizedSecret secret(); 75 | 76 | @JsonProperty 77 | public abstract List groups(); 78 | 79 | /** @return Name to serialize for clients. */ 80 | public static String displayName(SanitizedSecretWithGroups sanitizedSecretWithGroups) { 81 | String name = sanitizedSecretWithGroups.secret().name(); 82 | return name; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/keywhiz/model/v2/CreateOrUpdateSecretRequestV2.java: -------------------------------------------------------------------------------- 1 | package com.oneops.proxy.keywhiz.model.v2; 2 | 3 | import com.fasterxml.jackson.annotation.*; 4 | import com.google.auto.value.AutoValue; 5 | import com.google.common.base.*; 6 | import com.google.common.collect.ImmutableMap; 7 | import java.util.*; 8 | import javax.annotation.Nullable; 9 | 10 | @AutoValue 11 | public abstract class CreateOrUpdateSecretRequestV2 { 12 | CreateOrUpdateSecretRequestV2() {} // prevent sub-classing 13 | 14 | public static Builder builder() { 15 | return new AutoValue_CreateOrUpdateSecretRequestV2.Builder() 16 | .description("") 17 | .metadata(ImmutableMap.of()) 18 | .expiry(0) 19 | .type(""); 20 | } 21 | 22 | @AutoValue.Builder 23 | public abstract static class Builder { 24 | // intended to be package-private 25 | abstract String content(); 26 | 27 | abstract CreateOrUpdateSecretRequestV2 autoBuild(); 28 | 29 | public abstract Builder content(String content); 30 | 31 | public abstract Builder description(String description); 32 | 33 | public abstract Builder metadata(ImmutableMap metadata); 34 | 35 | public abstract Builder type(String type); 36 | 37 | public abstract Builder expiry(long expiry); 38 | 39 | /** @throws IllegalArgumentException if builder data is invalid. */ 40 | public CreateOrUpdateSecretRequestV2 build() { 41 | // throws IllegalArgumentException if content not valid base64. 42 | Base64.getDecoder().decode(content()); 43 | 44 | CreateOrUpdateSecretRequestV2 request = autoBuild(); 45 | return request; 46 | } 47 | } 48 | 49 | /** Static factory method used by Jackson for deserialization */ 50 | @SuppressWarnings("unused") 51 | @JsonCreator 52 | public static CreateOrUpdateSecretRequestV2 fromParts( 53 | @JsonProperty("content") String content, 54 | @JsonProperty("description") @Nullable String description, 55 | @JsonProperty("metadata") @Nullable Map metadata, 56 | @JsonProperty("expiry") long expiry, 57 | @JsonProperty("type") @Nullable String type) { 58 | return builder() 59 | .content(content) 60 | .description(Strings.nullToEmpty(description)) 61 | .metadata(metadata == null ? ImmutableMap.of() : ImmutableMap.copyOf(metadata)) 62 | .expiry(expiry) 63 | .type(Strings.nullToEmpty(type)) 64 | .build(); 65 | } 66 | 67 | @JsonProperty("content") 68 | public abstract String content(); 69 | 70 | @JsonProperty("description") 71 | public abstract String description(); 72 | 73 | @JsonProperty("metadata") 74 | public abstract ImmutableMap metadata(); 75 | 76 | @JsonProperty("expiry") 77 | public abstract long expiry(); 78 | 79 | @JsonProperty("type") 80 | public abstract String type(); 81 | 82 | @Override 83 | public final String toString() { 84 | return MoreObjects.toStringHelper(this) 85 | .add("content", "[REDACTED]") 86 | .add("description", description()) 87 | .add("metadata", metadata()) 88 | .add("expiry", expiry()) 89 | .add("type", type()) 90 | .omitNullValues() 91 | .toString(); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /docs/javadocs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | OneOps Secrets Proxy 1.2.1-SNAPSHOT API 8 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | <noscript> 70 | <div>JavaScript is disabled on your browser.</div> 71 | </noscript> 72 | <h2>Frame Alert</h2> 73 | <p>This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client. Link to <a href="overview-summary.html">Non-frame version</a>.</p> 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/main/java/com/oneops/proxy/auth/user/OneOpsUser.java: -------------------------------------------------------------------------------- 1 | /** 2 | * ***************************************************************************** 3 | * 4 | *

Copyright 2017 Walmart, Inc. 5 | * 6 | *

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file 7 | * except in compliance with the License. You may obtain a copy of the License at 8 | * 9 | *

http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | *

Unless required by applicable law or agreed to in writing, software distributed under the 12 | * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 13 | * express or implied. See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | *

***************************************************************************** 17 | */ 18 | package com.oneops.proxy.auth.user; 19 | 20 | import com.fasterxml.jackson.annotation.JsonIgnoreProperties; 21 | import com.oneops.proxy.authz.AuthDomain; 22 | import java.util.Collection; 23 | import org.springframework.security.core.GrantedAuthority; 24 | import org.springframework.security.core.userdetails.User; 25 | import org.springframework.security.core.userdetails.UserDetails; 26 | 27 | /** 28 | * OneOps user details. The user credential (password) is ignored from JSON serialization in 29 | * case it's used as Rest controller response. 30 | * 31 | * @author Suresh 32 | */ 33 | @JsonIgnoreProperties("password") 34 | public class OneOpsUser extends User { 35 | 36 | private final String cn; 37 | 38 | private final AuthDomain domain; 39 | 40 | /** 41 | * Creates a new OneOps user from the {@link UserDetails} object. 42 | * 43 | * @param user user details. 44 | */ 45 | public OneOpsUser(User user) { 46 | this( 47 | user.getUsername(), 48 | user.getPassword(), 49 | user.getAuthorities(), 50 | user.getUsername(), 51 | AuthDomain.PROD); 52 | } 53 | 54 | public OneOpsUser( 55 | String username, 56 | String password, 57 | Collection authorities, 58 | String cn, 59 | AuthDomain domain) { 60 | super(username, password, authorities); 61 | this.cn = cn; 62 | this.domain = domain; 63 | } 64 | 65 | /** Returns OneOps mgmt domain. */ 66 | public AuthDomain getDomain() { 67 | return domain; 68 | } 69 | 70 | /** Returns the OneOps user common name. Usually it's your full name. */ 71 | public String getCn() { 72 | return cn; 73 | } 74 | 75 | /** 76 | * Checks whether the user has given role. 77 | * 78 | * @param role {@link Role} 79 | * @return true if the user has given authority. 80 | */ 81 | public boolean hasRole(Role role) { 82 | return getAuthorities() 83 | .stream() 84 | .anyMatch(a -> a.getAuthority().equalsIgnoreCase(role.authority())); 85 | } 86 | 87 | /** OneOps user roles. */ 88 | public enum Role { 89 | USER, 90 | ADMIN, 91 | MGMT; 92 | 93 | /** 94 | * Authorities for this role name. 95 | * 96 | * @return role name prefixed with "ROLE_" 97 | */ 98 | public String authority() { 99 | return "ROLE_" + name(); 100 | } 101 | } 102 | } 103 | --------------------------------------------------------------------------------