Add support for credentials of type "ssh".

This commit is contained in:
Scott Frederick
2017-05-22 16:16:42 -05:00
parent 6cafccac40
commit 0cfe0385b8
8 changed files with 378 additions and 1 deletions

View File

@@ -26,6 +26,7 @@ import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import org.springframework.credhub.support.JsonCredential;
import org.springframework.credhub.support.PasswordCredential;
import org.springframework.credhub.support.RsaCredential;
import org.springframework.credhub.support.SshCredential;
import org.springframework.credhub.support.UserCredential;
import org.springframework.credhub.support.ValueCredential;
import org.springframework.credhub.support.ValueType;
@@ -66,6 +67,7 @@ public class JsonUtils {
new NamedType(ValueCredential.class, ValueType.VALUE.type()),
new NamedType(UserCredential.class, ValueType.USER.type()),
new NamedType(RsaCredential.class, ValueType.RSA.type()),
new NamedType(SshCredential.class, ValueType.SSH.type()),
new NamedType(JsonCredential.class, ValueType.JSON.type())
);
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
/**
* An SSH credential consists of a public and/or private key. At least one of these key values must be provided.
*
* @author Scott Frederick
*/
public class SshCredential extends KeyPairCredential {
/**
* Create an empty {@link SshCredential}. Intended to be used internally for deserialization of responses.
*/
private SshCredential() {
super();
}
/**
* Create an {@link SshCredential} from the provided public and private key. At least one of the key
* values must not be {@literal null}.
*
* @param publicKey the public key
* @param privateKey the private key
*/
public SshCredential(String publicKey, String privateKey) {
super(publicKey, privateKey);
}
}

View File

@@ -0,0 +1,67 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import org.springframework.util.Assert;
import static org.springframework.credhub.support.ValueType.SSH;
/**
* The details of a request to write a new or update an existing {@link SshCredential} in CredHub.
*
* @author Scott Frederick
*/
public class SshWriteRequest extends WriteRequest<SshCredential> {
/**
* Create a builder that provides a fluent API for providing the values required
* to construct a {@link SshWriteRequest}.
*
* @return a builder
*/
public static SshWriteRequestBuilder builder() {
return new SshWriteRequestBuilder();
}
/**
* A builder that provides a fluent API for constructing {@link SshWriteRequest}s.
*/
public static class SshWriteRequestBuilder
extends WriteRequestBuilder<SshCredential, SshWriteRequest, SshWriteRequestBuilder> {
@Override
protected SshWriteRequest createTarget() {
return new SshWriteRequest();
}
@Override
protected SshWriteRequestBuilder createBuilder() {
return this;
}
/**
* Set the value of an SSH credential.
*
* @param value the credential value; must not be {@literal null}
* @return the builder
*/
public SshWriteRequestBuilder value(SshCredential value) {
Assert.notNull(value, "value must not be null");
targetObj.setType(SSH);
targetObj.setValue(value);
return this;
}
}
}

View File

@@ -48,6 +48,12 @@ public enum ValueType {
*/
RSA("rsa"),
/**
* An SSH credential consists of a private key and/or public key. The values
* are provided by the client.
*/
SSH("ssh"),
/**
* A JSON credential consists of one or more fields in a JSON document. The keys and
* values in the JSON document are determined by the client.

View File

@@ -35,7 +35,7 @@ import org.springframework.http.ResponseEntity;
@RunWith(Theories.class)
public class CredHubTemplateDetailRsaUnitTests
extends CredHubTemplateDetailUnitTestsBase<RsaCredential> {
private static final RsaCredential CREDENTIAL = new RsaCredential("myname", "secret");
private static final RsaCredential CREDENTIAL = new RsaCredential("public-key", "private-key");
@DataPoints("detail-responses")
public static List<ResponseEntity<CredentialDetails<RsaCredential>>> buildDetailResponses() {

View File

@@ -0,0 +1,86 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.core;
import java.util.List;
import org.junit.experimental.theories.DataPoints;
import org.junit.experimental.theories.FromDataPoints;
import org.junit.experimental.theories.Theories;
import org.junit.experimental.theories.Theory;
import org.junit.runner.RunWith;
import org.springframework.credhub.support.CredentialDetails;
import org.springframework.credhub.support.CredentialDetailsData;
import org.springframework.credhub.support.SshCredential;
import org.springframework.credhub.support.SshWriteRequest;
import org.springframework.credhub.support.ValueType;
import org.springframework.credhub.support.WriteRequest;
import org.springframework.http.ResponseEntity;
@RunWith(Theories.class)
public class CredHubTemplateDetailSshUnitTests
extends CredHubTemplateDetailUnitTestsBase<SshCredential> {
private static final SshCredential CREDENTIAL = new SshCredential("public-key", "private-key");
@DataPoints("detail-responses")
public static List<ResponseEntity<CredentialDetails<SshCredential>>> buildDetailResponses() {
return buildDetailResponses(ValueType.RSA, CREDENTIAL);
}
@DataPoints("data-responses")
public static List<ResponseEntity<CredentialDetailsData<SshCredential>>> buildDataResponses() {
return buildDataResponses(ValueType.RSA, CREDENTIAL);
}
@Override
public WriteRequest<SshCredential> getRequest() {
return SshWriteRequest.builder()
.name(NAME)
.value(CREDENTIAL)
.build();
}
@Override
public Class<SshCredential> getType() {
return SshCredential.class;
}
@Theory
public void write(@FromDataPoints("detail-responses")
ResponseEntity<CredentialDetails<SshCredential>> expectedResponse) {
verifyWrite(expectedResponse);
}
@Theory
public void getById(@FromDataPoints("detail-responses")
ResponseEntity<CredentialDetails<SshCredential>> expectedResponse) {
verifyGetById(expectedResponse);
}
@Theory
public void getByNameWithString(@FromDataPoints("data-responses")
ResponseEntity<CredentialDetailsData<SshCredential>> expectedResponse) {
verifyGetByNameWithString(expectedResponse);
}
@Theory
public void getByNameWithCredentialName(@FromDataPoints("data-responses")
ResponseEntity<CredentialDetailsData<SshCredential>> expectedResponse) {
verifyGetByNameWithCredentialName(expectedResponse);
}
}

View File

@@ -0,0 +1,81 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
public class SshCredentialDetailsUnitTests extends JsonParsingUnitTestsBase {
private static final String SSH_CREDENTIALS =
" \"type\": \"ssh\"," +
" \"value\": {" +
" \"private_key\": \"private-key\"," +
" \"public_key\": \"public-key\"" +
" }";
@Test
public void deserializeDetailsWithPublicAndPrivateKeys() throws Exception {
CredentialDetails<SshCredential> data = parseDetails(SSH_CREDENTIALS, SshCredential.class);
assertDetails(data, "public-key", "private-key");
}
@Test
public void deserializeDetailsWithPublicKey() throws Exception {
final String credentials =
" \"type\": \"ssh\"," +
" \"value\": {" +
" \"public_key\": \"public-key\"" +
" }";
CredentialDetails<SshCredential> data = parseDetails(credentials, SshCredential.class);
assertDetails(data, "public-key", null);
}
@Test
public void deserializeDetailsWithPrivateKey() throws Exception {
final String credentials =
" \"type\": \"ssh\"," +
" \"value\": {" +
" \"private_key\": \"private-key\"" +
" }";
CredentialDetails<SshCredential> data = parseDetails(credentials, SshCredential.class);
assertDetails(data, null, "private-key");
}
@Test
public void deserializeDetailsData() throws Exception {
CredentialDetailsData<SshCredential> response = parseDetailsData(SSH_CREDENTIALS, SshCredential.class);
assertThat(response.getData().size(), equalTo(1));
CredentialDetails<SshCredential> data = response.getData().get(0);
assertDetails(data, "public-key", "private-key");
}
private void assertDetails(CredentialDetails<SshCredential> data, String publicKey, String privateKey) {
assertCommonDetails(data);
assertThat(data.getValueType(), equalTo(ValueType.SSH));
assertThat(data.getValue().getPublicKey(), equalTo(publicKey));
assertThat(data.getValue().getPrivateKey(), equalTo(privateKey));
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2016-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.credhub.support;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;
import static org.valid4j.matchers.jsonpath.JsonPathMatchers.hasJsonPath;
import static org.valid4j.matchers.jsonpath.JsonPathMatchers.hasNoJsonPath;
public class SshWriteRequestUnitTests extends WriteRequestUnitTestsBase {
@Before
public void setUp() {
buildRequest(new SshCredential("public-key", "private-key"));
}
@Test
public void serializeWithPublicAndPrivateKey() throws Exception {
String jsonValue = serializeToJson(requestBuilder);
assertThat(jsonValue,
allOf(hasJsonPath("$.overwrite", equalTo(true)),
hasJsonPath("$.name", equalTo("/c/example/credential")),
hasJsonPath("$.type", equalTo("ssh")),
hasJsonPath("$.value.public_key", equalTo("public-key")),
hasJsonPath("$.value.private_key", equalTo("private-key"))));
assertThat(jsonValue, hasNoJsonPath("$.additional_permissions"));
}
@Test
public void serializeWithPublicKey() throws Exception {
buildRequest(new SshCredential("public-key", null));
String jsonValue = serializeToJson(requestBuilder);
assertThat(jsonValue,
allOf(hasJsonPath("$.overwrite", equalTo(true)),
hasJsonPath("$.name", equalTo("/c/example/credential")),
hasJsonPath("$.type", equalTo("ssh")),
hasJsonPath("$.value.public_key", equalTo("public-key")),
hasNoJsonPath("$.value.private_key")));
assertThat(jsonValue, hasNoJsonPath("$.additional_permissions"));
}
@Test
public void serializeWithPrivateKey() throws Exception {
buildRequest(new SshCredential(null, "private-key"));
String jsonValue = serializeToJson(requestBuilder);
assertThat(jsonValue,
allOf(hasJsonPath("$.overwrite", equalTo(true)),
hasJsonPath("$.name", equalTo("/c/example/credential")),
hasJsonPath("$.type", equalTo("ssh")),
hasNoJsonPath("$.value.public_key"),
hasJsonPath("$.value.private_key", equalTo("private-key"))));
assertThat(jsonValue, hasNoJsonPath("$.additional_permissions"));
}
@Test(expected = IllegalArgumentException.class)
public void serializeWithNeitherKey() throws Exception {
buildRequest(new SshCredential(null, null));
String jsonValue = serializeToJson(requestBuilder);
}
private void buildRequest(SshCredential value) {
requestBuilder = SshWriteRequest.builder()
.name(new SimpleCredentialName("example", "credential"))
.overwrite(true)
.value(value);
}
}