Merge branch 'master' into ui-fix-select-arrow

This commit is contained in:
Joshua Ogle 2019-04-28 18:37:05 -05:00 committed by GitHub
commit 353c1e48fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
90 changed files with 713 additions and 3513 deletions

View File

@ -13,6 +13,10 @@ IMPROVEMENTS:
BUG FIXES:
* replication: Fix an issue causing startup problems if a namespace policy
wasn't replicated properly
* replication: Properly update mount entry cache on a secondary to apply all
new values after a tune
* ui: fix an issue where sensitive input values weren't being saved to the
server [GH-6586]

View File

@ -12,7 +12,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=

View File

@ -159,6 +159,7 @@ type MountConfigInput struct {
}
type MountOutput struct {
UUID string `json:"uuid"`
Type string `json:"type"`
Description string `json:"description"`
Accessor string `json:"accessor"`

View File

@ -1112,18 +1112,34 @@ func TestBackend_ext_singleCert(t *testing.T) {
// Test a self-signed client with URI alt names (root CA) that is trusted
func TestBackend_dns_singleCert(t *testing.T) {
connState, err := testConnState(
"test-fixtures/root/rootcawdnscert.pem",
"test-fixtures/root/rootcawdnskey.pem",
"test-fixtures/root/rootcacert.pem",
)
certTemplate := &x509.Certificate{
Subject: pkix.Name{
CommonName: "example.com",
},
DNSNames: []string{"example.com"},
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth,
},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement,
SerialNumber: big.NewInt(mathrand.Int63()),
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
}
tempDir, connState, err := generateTestCertAndConnState(t, certTemplate)
if tempDir != "" {
defer os.RemoveAll(tempDir)
}
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
ca, err := ioutil.ReadFile(filepath.Join(tempDir, "ca_cert.pem"))
if err != nil {
t.Fatalf("err: %v", err)
}
logicaltest.Test(t, logicaltest.TestCase{
CredentialBackend: testFactory(t),
Steps: []logicaltest.TestStep{
@ -1143,18 +1159,34 @@ func TestBackend_dns_singleCert(t *testing.T) {
// Test a self-signed client with URI alt names (root CA) that is trusted
func TestBackend_email_singleCert(t *testing.T) {
connState, err := testConnState(
"test-fixtures/root/rootcawemailcert.pem",
"test-fixtures/root/rootcawemailkey.pem",
"test-fixtures/root/rootcacert.pem",
)
certTemplate := &x509.Certificate{
Subject: pkix.Name{
CommonName: "example.com",
},
EmailAddresses: []string{"valid@example.com"},
IPAddresses: []net.IP{net.ParseIP("127.0.0.1")},
ExtKeyUsage: []x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth,
},
KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment | x509.KeyUsageKeyAgreement,
SerialNumber: big.NewInt(mathrand.Int63()),
NotBefore: time.Now().Add(-30 * time.Second),
NotAfter: time.Now().Add(262980 * time.Hour),
}
tempDir, connState, err := generateTestCertAndConnState(t, certTemplate)
if tempDir != "" {
defer os.RemoveAll(tempDir)
}
if err != nil {
t.Fatalf("error testing connection state: %v", err)
}
ca, err := ioutil.ReadFile("test-fixtures/root/rootcacert.pem")
ca, err := ioutil.ReadFile(filepath.Join(tempDir, "ca_cert.pem"))
if err != nil {
t.Fatalf("err: %v", err)
}
logicaltest.Test(t, logicaltest.TestCase{
CredentialBackend: testFactory(t),
Steps: []logicaltest.TestStep{

View File

@ -1,17 +0,0 @@
[ req ]
default_bits = 2048
encrypt_key = no
prompt = no
default_md = sha256
req_extensions = req_v3
distinguished_name = dn
[ dn ]
CN = example.com
[ req_v3 ]
subjectAltName = @alt_names
[ alt_names ]
IP.1 = 127.0.0.1
DNS.1 = example.com

View File

@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIEijCCAnICAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3
DQEBAQUAA4ICDwAwggIKAoICAQDUJ6s97BFxR295bCjpwQ85Vo8DnBFa/awNH107
QFn/zw0ZDdJMLtEBc/bw7pTYw5ulKbiZDFrmzPEY+QZlo+t1TeWgPRJg0CbYNukS
aNv0vKXjDXYwbrCyOvZucy8hte6IKjZfH+kAsgbbUxfD75BCKsxMxbVHkg0W9Ma2
pnZj/kpvQE5lkMj5mDvtWdfCRsVg4zL6jhRHkPZ6fOkF3mrfTbQu3oyOcbKLEE/G
t3QRKw3uv0vMDmhg62ZPvD1k70UMjUV2MVqEPZuWY7/bbW8OsfzMyBOGY9LLp7QS
krxWYRj6SPUR4f1bZq7pRbqOfS0okq/XDLf1k6Na5cT6iNdyjEVdSJl7vR7kSreX
8hkwK46Oup8v/vJLu/cRDCpAas0gJJkJDPt5114V0/Xww7EFxs5GijXP8i5RLlgK
/nRscbK+fgjQOnQ5cp0pcP8HAriy2vil7E0fQvMvt5QTyINEYgiYaCIT9WGRC8Xo
WcoUGI2vyrGy6RU6A3/TKeBLtikaSPjFKa1dFTAHfrUkTBpfqc+sbiJ334Bvucg5
WyS8oAC5Vf++iMnETSdzx1k0/QARVLD38PO8wPaPU1M2XaSA+RHTB9SGFc4VTauT
B167NLlmgJHYuhp+KM1RTy1TEoDlJh2qKj21BLcR1GJ0KgDze6Vpf9xdRTdqMpo2
h20wdQIDAQABoC8wLQYJKoZIhvcNAQkOMSAwHjAcBgNVHREEFTAThwR/AAABggtl
eGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAGtds+2IUVKzw9bi130mBbb9K
CrXw2NXSp+LJwneIEy0bjAaNr7zCGQsj7q57qFwjc7vLTtGRheP5myrAOq00lp8J
1sGZSETS/y4yeITLZSYWVq2dtF/hY9I+X3uOoibdsQgzYqhBcUr4oTDapf1ZEs0i
wA2J5IcasfaBpWFc9wRN79BBACLGyCbX6VwUISrGe3Hgzkeqtg97cU62ecQsgXiZ
LdQgERvC0wSfAmI4lGulXi1oYYSRxXQ8pEKEAMeJrJVQfvhdbS/o4Bdf3Yj6ibtD
tFSdKLcdRCfMQBEHNpSh665LfBbwU55Fh89tBdGmf6uqsimUY6AxNncnLsc1Kq6F
oINXix3GsBNmCahDeHdGOlNjw0Lpl0m6bnu6LXSDwwuNWAEdDfEmxR+5T/GkGxcG
TTWPwEkpnCe4VmGl9Y10uPSvqneNsdNWjDVK4BeW4VSf9Lp1Zeme1dYFvpyzow+r
4ogpvMPf5vy5I/0HCEf1KlaPyhs8ZGK6YBGaeEDYSaysAWJfYm8eiqwUuKYj/FUe
G3KkaFpOGsQHFNRtG8GukV3r2AK97HFHKNfygZ2xvk5isXz2ZsNX1/J0+GGjalJl
cWBBEiXFM94XJHE9rACsL2UKn8cWCh9lHNLlePOkQuoNY9CUd63xx4Hg97XWP3+U
DhpG7CADsKcPJfbMgrk=
-----END CERTIFICATE REQUEST-----

View File

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIDzzCCAregAwIBAgIJAJIiPq+77herMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV
BAMTC2V4YW1wbGUuY29tMB4XDTE4MDQyNjEyMDEzMFoXDTE5MDQyNjEyMDEzMFow
FjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQDUJ6s97BFxR295bCjpwQ85Vo8DnBFa/awNH107QFn/zw0ZDdJMLtEB
c/bw7pTYw5ulKbiZDFrmzPEY+QZlo+t1TeWgPRJg0CbYNukSaNv0vKXjDXYwbrCy
OvZucy8hte6IKjZfH+kAsgbbUxfD75BCKsxMxbVHkg0W9Ma2pnZj/kpvQE5lkMj5
mDvtWdfCRsVg4zL6jhRHkPZ6fOkF3mrfTbQu3oyOcbKLEE/Gt3QRKw3uv0vMDmhg
62ZPvD1k70UMjUV2MVqEPZuWY7/bbW8OsfzMyBOGY9LLp7QSkrxWYRj6SPUR4f1b
Zq7pRbqOfS0okq/XDLf1k6Na5cT6iNdyjEVdSJl7vR7kSreX8hkwK46Oup8v/vJL
u/cRDCpAas0gJJkJDPt5114V0/Xww7EFxs5GijXP8i5RLlgK/nRscbK+fgjQOnQ5
cp0pcP8HAriy2vil7E0fQvMvt5QTyINEYgiYaCIT9WGRC8XoWcoUGI2vyrGy6RU6
A3/TKeBLtikaSPjFKa1dFTAHfrUkTBpfqc+sbiJ334Bvucg5WyS8oAC5Vf++iMnE
TSdzx1k0/QARVLD38PO8wPaPU1M2XaSA+RHTB9SGFc4VTauTB167NLlmgJHYuhp+
KM1RTy1TEoDlJh2qKj21BLcR1GJ0KgDze6Vpf9xdRTdqMpo2h20wdQIDAQABoyAw
HjAcBgNVHREEFTAThwR/AAABggtleGFtcGxlLmNvbTANBgkqhkiG9w0BAQUFAAOC
AQEA2JswcCYtHvOm2QmSEVeFcCeVNkzr35FXATamJv0oMMjjUFix78MW03EW6vJa
E52e3pBvRdy+k2fuq/RtHIUKzB6jNbv0Vds26Dq+pmGeoaQZOW94/Wht7f9pZgBi
IRPBg9oACtyNAuDsCOdetOyvyoU29sjUOUoQZbEXF+FK4lRJrEmZUJHbp/BOD58V
mQRtjTMjQlZZropqBQmooMRYU0qgWHaIjyoQpu2MgEj3+/1b1IX6SCfRuit0auh/
YI3/cCtyAG/DpZ6zfyXuyY+iN+l8B6t0nXyV3g8JgBWYPGJv1hgVIgnnqlwuL517
mEAT5RnHCNJQNuzS1dwfuBrX3w==
-----END CERTIFICATE-----

View File

@ -1,52 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDUJ6s97BFxR295
bCjpwQ85Vo8DnBFa/awNH107QFn/zw0ZDdJMLtEBc/bw7pTYw5ulKbiZDFrmzPEY
+QZlo+t1TeWgPRJg0CbYNukSaNv0vKXjDXYwbrCyOvZucy8hte6IKjZfH+kAsgbb
UxfD75BCKsxMxbVHkg0W9Ma2pnZj/kpvQE5lkMj5mDvtWdfCRsVg4zL6jhRHkPZ6
fOkF3mrfTbQu3oyOcbKLEE/Gt3QRKw3uv0vMDmhg62ZPvD1k70UMjUV2MVqEPZuW
Y7/bbW8OsfzMyBOGY9LLp7QSkrxWYRj6SPUR4f1bZq7pRbqOfS0okq/XDLf1k6Na
5cT6iNdyjEVdSJl7vR7kSreX8hkwK46Oup8v/vJLu/cRDCpAas0gJJkJDPt5114V
0/Xww7EFxs5GijXP8i5RLlgK/nRscbK+fgjQOnQ5cp0pcP8HAriy2vil7E0fQvMv
t5QTyINEYgiYaCIT9WGRC8XoWcoUGI2vyrGy6RU6A3/TKeBLtikaSPjFKa1dFTAH
frUkTBpfqc+sbiJ334Bvucg5WyS8oAC5Vf++iMnETSdzx1k0/QARVLD38PO8wPaP
U1M2XaSA+RHTB9SGFc4VTauTB167NLlmgJHYuhp+KM1RTy1TEoDlJh2qKj21BLcR
1GJ0KgDze6Vpf9xdRTdqMpo2h20wdQIDAQABAoICAQDJxszUQQC554I7TsZ+xBJx
q0Sr3zSWgOuxM2Jdpy+x38AKUx3vPRulsSBtN8yzeR9Ab7TVQ231U3f/E2GlK8kW
sTazN0KSd4ZqX5c+3iJM21s+3p/JIo3FhdS5aa2q9zjdoqBByry135wr3xScUu22
MLRMVEG8x0jRy45vS1UQd1teAiBN8u1ijgp5DNjrOpohMxVaPeVFx7bU+pY58bdd
mK7FYP73v2VbY/EsA3FNntBKgQBbHFzjyR9uuI7/v53BeV9WMUxwt5OR7l8cGDHn
HRtdvPDtAWYMMf1PKOYdlY3HBbqn/nMUCk5TKPFs8dsQWqsI8lzIIVndauj0i0+0
M/lVMXu4x48o5FfLa4HjkpcDxAU6QDHA9thaDkasZebixVH/p1ZJkLORl5jDLYkU
Av+B3i1efITwNYgosZNjPpw0PyYh9PV9JvB87d5wFpgISfZyRXpBVGeJbt6gg++8
8/5A/GzSpGy0FhLcP3vuVTcX2VOexjqeaoi4U3cHrbWv/wNj5a4BNk5EJT8fVeSb
+Emqydl9u3n2E315GPC8kwxdE3r3hGrWdZQn9byGvqzwDaLWXQLQWvQN4GOpGTrP
Yxj2Oi8s1MJHkppj4eo52O4J7cBlAJn3RFmlCKGOoWJZMdPktp/gWeT+xIGSaa21
qB+l/ZFEWLPMxdTBMGFmYQKCAQEA8DgozaZBXr7mb1H25EbW9YmtLc61JMapQrZb
ObygiGR6RZsxCXEvGdhvvmwpO8rA9wAOWqI8NV5GU8EvuRuwvGoX4HqbXkB6ZcyC
6RuZzki2lrKVGUaLc1v6MyhX4IzrqTYWDgQvwd9lMcUGR7r007KPE5ft4v3/TuxQ
qPKxQE7NO2xnTloUchd5g0/d975GZi0g6XDecFOuj43Pi0c/wRcFH6zfVirdcm+M
yP9CsJ/LUgtV1voLqyhfybwHvzpxJ0l25Fw+P85I4czosBp+FaFAwogxZEDnY8Fr
Hqcwdc7vwGDjTbtflDsUdppt2h8nD8bBZGysG8+P8HAt3i5D+QKCAQEA4heKueRQ
Y8nTZlmRSRtB6usRAeymQBJjO+yWwu/06Efg8VW5QRwtP0sx+syrLaQDy8MT07II
XQZmq55xATWbHCxULiceIY2KG5LHCovVotYAll8ov58exJva19C7/41uVrkl3H9j
xFLX0Bn3zMFKBOxKhygP2xqqEJdb1JJt27c2CbXvXOzqIZ4RCaNQdBdrlEiXQihR
JCGMUBfrYIwALQFzYuPGULhg77YcAi5owCPnfK+dDOOvMmW8BwPnRUc14WFIVV+m
dbY22WonLNPP055W5755Xl9RHKW1bcmIH6E4QZpMrlnd1UzPBQq1PJtcO3uRc5T6
CMQSUmwMGSQ3XQKCAQBiuVHborY+8AnYOkFTc+GoK5rmtosvwA2UA0neoqz/IPw3
Wx5+GOwYnSDfi6gukJdZa8Z6bS59aG9SwJSSaNTrulZxxTHRPIKRD8nFb7h4VN3l
dSNdreZl1KkxGSV0fbXkZvwNap8N+HeoSqbYF/fCgSHYFZqIrYadsvU7WfKK0Vf7
UgPq6Y55jTg9RTeeN67LE0Txa5efZmTZTpi7Tt7exk0uxWdMDHXSMBIWEQIhgKqY
31u57C2bfA5R5FrytlwGn2SjWV2j7214jzQaG+kxjoIE8OALqbjvAHC7uk5qPE/A
KpGAQr93Ngik7baz7BWroC2eziK1k0o+sHvJUg5RAoIBABF+ftZ5axr9j+T4gzxj
5orV24AJnqeQhKsrWFMHHC0o+qfR2T7HflzKZbihQ5GJgl2u34be3LTN/P3Eibvt
OO5KI81aa4NvH0OY7NvNDB/IbU01WcLR/iB6asmONi3E9MezFdHk7YRQYLCSgdEP
F7ofyniAyhFLE+OqwolFN0jr+TtxH29SSZ+GSo0zXNNOyJ01rLaKxhSEoAXGhAj5
bD4PQa1iMIMocR+7OJmWm7ZaUNwd/onzyCefJZhpXejHZMzmqSEqAIhVLBNQmm1m
iks2kkTmQR/jQjR0QgCXunewEtlIpixLedW6Vr5uIK3q240it5N48IvjGAPWpmz/
l2UCggEBALRlARlBdYcPhWbcyhq9suq2PJqHVvNdP9vVTZpPgmWgxmj9mPQ731Q/
UpRlBIk6U0qAxBXP9kzPqSivWhY8Jto80Jdr+/80PkdANDkpnXoDlxPk095sD2uN
Jv5FffFgMZH9MGpPTEuZ571/YtVi+1qFt0i3oazpF/g8gU23f2oxaX4xzsltVl8J
rWXYzmYE0i5Qiy81+zZ9dZlnmlKhcYpD6m2t/0hRAoNaoxOUV7WFcIzYIxpKvzYL
QTDL/Se2Ooc0xLQvM1oZ9/1NE2hpGQ/ipASEPlx9KO5ktYW7+LwdcSCMXtx84I/D
VQpWjPdILMpiVrB/9NsENTNv2DUvc+o=
-----END PRIVATE KEY-----

View File

@ -1,17 +0,0 @@
[ req ]
default_bits = 2048
encrypt_key = no
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = req_v3
[ req_v3 ]
subjectAltName = @alt_names
[ dn ]
CN = example.com
[ alt_names ]
IP.1 = 127.0.0.1
email = valid@example.com

View File

@ -1,27 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIEkDCCAngCAQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3
DQEBAQUAA4ICDwAwggIKAoICAQDO7stcdJQwUtVeJriwpAswDAirO827peSlgdxs
fW8X9M2hE9ihvESEILb7TRMRiFlDyQYg1BxKMrJ0DZmixFi8RvUCZbH6TFOUMsk+
w1FhpzjuqAqxNQ51s7u30sfruJg7XN3YJLEPelom62wvzhvLXJFLQZlQCDrMx+PC
ofWs4IA7jR8JaXZjIGdkEU0GgRPy8zKPUe3dUBHi2UR4eKT4cRCn4IwCrFx4BQjV
AxNKNDGpe+fTVOzII/UX+FppDdGZZ4g0y3E1mQUEKkff4dKCK7vhlGJR9D+5v/V0
/stwP72aXczijuVtnXXyli+oj24NaijoqQluNCD3MvV/INovLL2Tyk54H3/GvpU1
+sJbpE2+UPh+Rh8DNkT6RPRguymJO8MSsdLt/qvVD8BlZ7I9V3XZlDKosCRTUyxf
jjFpa+VzB3nt7uFtIXZ9HNGhQIpOULvkFGizWV+tS8PpGdTFVzDjyWg0HUKWn8g8
IiWR9S40h6mHjVuTuxA9tlO69PuTjGK7MlAvFTDaPC8seau1LUiqtQ+prnSLI0h1
6GfI9W2G7BKKVPloErODhLcsOcwRcmaJVW+yBda3te8+cMBIvtQYKAYSCtg8qXws
xyfPLo4GChbGGRbRCuM3mB1lG1qHEivJ0vynsgolp0t8jaXSFVBVgYj+C6Vd9/hl
ieUcOwIDAQABoDUwMwYJKoZIhvcNAQkOMSYwJDAiBgNVHREEGzAZhwR/AAABgRF2
YWxpZEBleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAAOCAgEAe1u3wYMMKaZ3d5Wz
jKH971CF3sl+KYl+oV0ekD8dbYe+szERgajn6Y5IYVxxi5o9UgeAWqnyHCiqsW8T
MQdUwMa67Ym/pHKSVoBlGePAKHqock0+iSsVBMcPpU9RkxdSW2aVtdb0DGfyB952
t3dSb0LaITu30fe8p7lxrL0DKESbwd4N2XQE1F5Vf+1OodvpJinn4Wqzn45hqRf0
imxrCgVjT5VtR+NRzKCK3Msmh+cJGpR3zgXwGKqgHLWzhvSoQwRWYE3apMK5xLk7
N1sWVxEKK5+L/CDaMNGQFx5lPiCN3bUudCq4uSZcPLO5AuDpSeLKnknBrWA6HcbB
WvnwtKmHeVe2qogPViKGuwE16rnPlp9hysPl2ckmtqEsXRagIAh5fMI3OoRbZmVV
jfJm21U4YkUWuMKet3EU1StT6T8T6O7QEFA4w4s5+m3dsjDZ9iTuK9/dCs1xnIke
4uJYmh3YrNl8IjMffJuWxA+/de3JO1UljC2EAFxa5KAc24+qyeWwky4tMv72gTOp
6q3k2wnsrK5B1errRV37OLgxtoh1I3Rgp+0B77SOK/PpD/JJazJG5O9bBJOvHJc0
STW9Td2CzgC2lKGfvkX6UYgVy/9HDq7/EKXP/G2f3kRik2NPUhGcnAH9nyL9SvpP
+T4CZ+FumDj5DulARk6arSq+uy4=
-----END CERTIFICATE REQUEST-----

View File

@ -1,23 +0,0 @@
-----BEGIN CERTIFICATE-----
MIID1TCCAr2gAwIBAgIJAJIiPq+77hevMA0GCSqGSIb3DQEBBQUAMBYxFDASBgNV
BAMTC2V4YW1wbGUuY29tMB4XDTE4MDQyNjEyMjE1MloXDTE5MDQyNjEyMjE1Mlow
FjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
ggIKAoICAQDO7stcdJQwUtVeJriwpAswDAirO827peSlgdxsfW8X9M2hE9ihvESE
ILb7TRMRiFlDyQYg1BxKMrJ0DZmixFi8RvUCZbH6TFOUMsk+w1FhpzjuqAqxNQ51
s7u30sfruJg7XN3YJLEPelom62wvzhvLXJFLQZlQCDrMx+PCofWs4IA7jR8JaXZj
IGdkEU0GgRPy8zKPUe3dUBHi2UR4eKT4cRCn4IwCrFx4BQjVAxNKNDGpe+fTVOzI
I/UX+FppDdGZZ4g0y3E1mQUEKkff4dKCK7vhlGJR9D+5v/V0/stwP72aXczijuVt
nXXyli+oj24NaijoqQluNCD3MvV/INovLL2Tyk54H3/GvpU1+sJbpE2+UPh+Rh8D
NkT6RPRguymJO8MSsdLt/qvVD8BlZ7I9V3XZlDKosCRTUyxfjjFpa+VzB3nt7uFt
IXZ9HNGhQIpOULvkFGizWV+tS8PpGdTFVzDjyWg0HUKWn8g8IiWR9S40h6mHjVuT
uxA9tlO69PuTjGK7MlAvFTDaPC8seau1LUiqtQ+prnSLI0h16GfI9W2G7BKKVPlo
ErODhLcsOcwRcmaJVW+yBda3te8+cMBIvtQYKAYSCtg8qXwsxyfPLo4GChbGGRbR
CuM3mB1lG1qHEivJ0vynsgolp0t8jaXSFVBVgYj+C6Vd9/hlieUcOwIDAQABoyYw
JDAiBgNVHREEGzAZhwR/AAABgRF2YWxpZEBleGFtcGxlLmNvbTANBgkqhkiG9w0B
AQUFAAOCAQEAp2T99t93hxPyCDaqfTF0lsdzIgxZ5GkSzYTYQ2pekLfMDUUy4WFQ
AppdnSJSpm6b+xWO2DkO8UAgOdSEORf/Qpfm+UpHaEYZlQiWQ0zNmIQgBoh6indU
bEZKeL6aAOfIshPNfmqjFt+DpEClrQvCHJggG/rB77Ujj6hPY2+8h4JjbjeX7Pe9
oUEx9LpZ5Qpo6PK5vB537PP7Q2qp2PIr29DLz1VeLCbqUnV+j7qT0T3hhqurnpTA
QUiRZI0etgeP/B5lw/S4AWijq+R6RasdPAS4UNHsYK+PSGiqdhW/bJvSx5UBXQbk
DuY2A4kdv60H5Aw45/F6enH2Fg1kg7PlQA==
-----END CERTIFICATE-----

View File

@ -1,52 +0,0 @@
-----BEGIN PRIVATE KEY-----
MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQDO7stcdJQwUtVe
JriwpAswDAirO827peSlgdxsfW8X9M2hE9ihvESEILb7TRMRiFlDyQYg1BxKMrJ0
DZmixFi8RvUCZbH6TFOUMsk+w1FhpzjuqAqxNQ51s7u30sfruJg7XN3YJLEPelom
62wvzhvLXJFLQZlQCDrMx+PCofWs4IA7jR8JaXZjIGdkEU0GgRPy8zKPUe3dUBHi
2UR4eKT4cRCn4IwCrFx4BQjVAxNKNDGpe+fTVOzII/UX+FppDdGZZ4g0y3E1mQUE
Kkff4dKCK7vhlGJR9D+5v/V0/stwP72aXczijuVtnXXyli+oj24NaijoqQluNCD3
MvV/INovLL2Tyk54H3/GvpU1+sJbpE2+UPh+Rh8DNkT6RPRguymJO8MSsdLt/qvV
D8BlZ7I9V3XZlDKosCRTUyxfjjFpa+VzB3nt7uFtIXZ9HNGhQIpOULvkFGizWV+t
S8PpGdTFVzDjyWg0HUKWn8g8IiWR9S40h6mHjVuTuxA9tlO69PuTjGK7MlAvFTDa
PC8seau1LUiqtQ+prnSLI0h16GfI9W2G7BKKVPloErODhLcsOcwRcmaJVW+yBda3
te8+cMBIvtQYKAYSCtg8qXwsxyfPLo4GChbGGRbRCuM3mB1lG1qHEivJ0vynsgol
p0t8jaXSFVBVgYj+C6Vd9/hlieUcOwIDAQABAoICAQDFitqh6TxqITlFBwv6vK9d
b696371XrFdo1F57RwcdxHnkklCUnWh/BcgIgJx6eUJV3nq2LibPgjQva6hF5NCc
89QDNNfBjMmgyRaqjsSKx5sm4U5Lus2R+UFzi4mEcpUI3m99XhGVKAUV8Fo4DLcl
3LlrMTVNXH3dbdj0va4NGcfwkZiWYJI+sPliYs24LtK/dADJJro/MqfQef7OTsWV
0kHHMSoXhzlC7fNvfd8VUFw0Ym99pC3iJclc155feWyk2FwDok7xjqFmR4KTrD1M
PLm/7+ooOFX5WdHVnULSZlb3HSJxCV7l1JJ7QXo/nKS/s59X875n8OWjdoc7lD4T
Xw/K9CzJCyhJ/HDhTAea1+MNTig4a6wjdSim6vasig/Gkot6jjS2lhnZae8ZhYxP
GUx4JcPthHppgHt8s6Jb2PHuqNVRmVB0x41c5mmXOnJcSqOX0XhbSbeS1TUV8BiC
HMaa+agt7RpQOb5uxpb+Hath/88tsjDXI0ZHNAG43ndkHxSQQ9P/q/m5uaLwuJyo
Yb06yUy/g7ceXpJFjGsjO+33DmamvligqOswgg+oazMFo8S9ZUJw6sSXhM/XiHla
JOj+Vatfj0ViVcaGlO2kWughuCT5thn92bgC9V2VnJhbaSzSaQlRphlbuSYJEYj0
S1uIbwPzTrcBQuekwY50YQKCAQEA/vve5K/nAnw4KLSrKwwCp9trYSm8C5czv2jV
tn6vQtckQMrw/hubX7TcTTgTuGboGdHMwZMFJBKpx6AlRHCR5IBw8fR1z+58c+2V
VJgllc23eKwCcBMKoe6LmsiUXOWmc7MuHc+qQS+9OemO93nNafsSwFCkucBFQs/3
Yx7J3zNvMOuy+dq3jrxO0xl2jBF0pcmJF/czrvbMCD7tvDntgqvpAnybgrwm2cu3
Q5F6i+E5w6VDhCprQL/aK95iT7cPmfdGxsUCdfNzDGIJFHZp2Hrar1TsOP6ESsDl
Q/Oz9oO1vMy7MymJjWFoVELBlCBxDEgubyM1f8cE1tQ6UAqFSwKCAQEAz8HnKWPe
NWZtqdAzSmY+3ZxSe1BbukOo4XtCV8LfRHGazKpXMTqsO9l7ynK7ifXv3b3GHTr+
ck2Af/vyiVx6f7Ty2dmBotFQDzg0HfKD2skAPyH8cHpA8TUeL3yMOR3XQU5/pOnG
tn84n7KWpAyZXh8gzMnmzWjMlb9pUlkKcATUj0gb8iSa9PV0zBwMKYKY0ngznJT2
CgE1vhy59rpuUVMrQ8i5iW9jbqYVrqID+ta2DWgcLsEXft7jKfupnRHF0Dvc650p
+Lkxv0YgKjUg5sYc2QJbIiBxXaW0cTRrw/KfOe4kvdG5RMF60Six+W1DIW2l+qi3
irnDRvRm1N6e0QKCAQEA86d5MaxJIl3TSEqEeikK7J3GuV0pHSZKQ7EI70+VaFiv
gt6qdReqXEU2cu+QIJjtV6bcc2lq8zKGXITSt9ieAO0fgIWqgpyQ/jJcjS6qU8D1
fnFYDwKTGXQaoTjkVPT6HvtsqP4E4i+dMZbWj/MrcAeEvpMRJZLuXE7gRi5ol0nO
CcBhEVKILvQQmrZtSqFvhvDTeTw2fg3FoGeJw2DTbheaHE84RzBGK774C7Abm0kI
asUkhEoInSH3eA4UgbobRXQ+hLhDhrSxDncr2ArjUALtr7eF11yWy9wR+OIK6Rio
9JXqmJQrphcbm9ECq+poPGVJQdgySjzCigrZAh1biwKCAQBiBnFVXCOaOov/lZa9
weRjl8BrIo1FI2tpiEjTM8U4fAm4C588QRzG2GTKLrxB6eKVU1dIr28i62J4AJ59
JT8/RldXZoL+GZiWtcQRZT3FWxVctGJxh51gsdleOnvG70eDLtCXNR5nOTu0TgU5
viAXAsTtG05lGM9+0GOXUR/VntHUEQfuhkr+zVmgfJNYeqA0njZr6PT134BGBTPR
MEGg6Yb+YpT4PbBCouaUESmjju8zAC5b+Qtm9y9jvbRXwez9xWEFYpBNJMROJX5D
q/GsMUmnMq9hOMGEmAy9ZSh7udxa7vwy++NYh5m1Wmgu8di8ywmHbVe8gs2aivKB
+dAhAoIBAQC7nSuRSmRGeKJCAqikMFPVdFdLaTnEw4i/fcyYsPa+o2hTWXyLll8K
lwSnBxe+BCvdeQ8cWzg3rPaIBVzUjDecZjdwjcHnhlHvgHjEvFX339rvpD7J2HIb
DaVqvtPniCFdNK4Jyvd3JMtNq34SIHFAcmB9358JuKsOwCmk8CpMAqKPVsKj7m6H
ETISh/K8aI2vZxVZ4WN4FsQTCqmtQDXFSGpZF5EZSpMJIB3ZZLt2jyyDW2DaZ+1T
yuVl9jU56fTtacQROQY7cvrwznX0lFpmniwl0Aj0wln/svFAqKo1+RujqApw5iYn
ssH1dH2tESx6RpMMyLYihjHVDC/ULUVu
-----END PRIVATE KEY-----

View File

@ -7,6 +7,7 @@ import (
"net/http"
"os"
"reflect"
"strings"
"sync"
"testing"
"time"
@ -556,6 +557,27 @@ func describeAzsTestUnauthorized(accessKey, secretKey, token string) error {
})
}
func assertCreatedIAMUser(accessKey, secretKey, token string) error {
creds := credentials.NewStaticCredentials(accessKey, secretKey, token)
awsConfig := &aws.Config{
Credentials: creds,
Region: aws.String("us-east-1"),
HTTPClient: cleanhttp.DefaultClient(),
}
client := iam.New(session.New(awsConfig))
log.Printf("[WARN] Checking if IAM User is created properly...")
userOutput, err := client.GetUser(&iam.GetUserInput{})
if err != nil {
return err
}
if *userOutput.User.Path != "/path/" {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", userOutput.User.Path, "/path/")
}
return nil
}
func listIamUsersTest(accessKey, secretKey, token string) error {
creds := credentials.NewStaticCredentials(accessKey, secretKey, token)
awsConfig := &aws.Config{
@ -647,12 +669,13 @@ func testAccStepReadPolicy(t *testing.T, name string, value string) logicaltest.
}
expected := map[string]interface{}{
"policy_arns": []string(nil),
"role_arns": []string(nil),
"policy_document": value,
"credential_types": []string{iamUserCred, federationTokenCred},
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"policy_arns": []string(nil),
"role_arns": []string(nil),
"policy_document": value,
"credential_type": strings.Join([]string{iamUserCred, federationTokenCred}, ","),
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "",
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)
@ -743,15 +766,18 @@ func TestBackend_iamUserManagedInlinePolicies(t *testing.T) {
"policy_document": testDynamoPolicy,
"policy_arns": []string{ec2PolicyArn, iamPolicyArn},
"credential_type": iamUserCred,
"user_path": "/path/",
}
expectedRoleData := map[string]interface{}{
"policy_document": compacted,
"policy_arns": []string{ec2PolicyArn, iamPolicyArn},
"credential_types": []string{iamUserCred},
"role_arns": []string(nil),
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"policy_document": compacted,
"policy_arns": []string{ec2PolicyArn, iamPolicyArn},
"credential_type": iamUserCred,
"role_arns": []string(nil),
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "/path/",
}
logicaltest.Test(t, logicaltest.TestCase{
AcceptanceTest: true,
PreCheck: func() { testAccPreCheck(t) },
@ -760,7 +786,7 @@ func TestBackend_iamUserManagedInlinePolicies(t *testing.T) {
testAccStepConfig(t),
testAccStepWriteRole(t, "test", roleData),
testAccStepReadRole(t, "test", expectedRoleData),
testAccStepRead(t, "creds", "test", []credentialTestFunc{describeInstancesTest, listIamUsersTest, listDynamoTablesTest}),
testAccStepRead(t, "creds", "test", []credentialTestFunc{describeInstancesTest, listIamUsersTest, listDynamoTablesTest, assertCreatedIAMUser}),
testAccStepRead(t, "sts", "test", []credentialTestFunc{describeInstancesTest, listIamUsersTest, listDynamoTablesTest}),
},
})
@ -881,12 +907,13 @@ func testAccStepReadArnPolicy(t *testing.T, name string, value string) logicalte
}
expected := map[string]interface{}{
"policy_arns": []string{value},
"role_arns": []string(nil),
"policy_document": "",
"credential_types": []string{iamUserCred},
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"policy_arns": []string{value},
"role_arns": []string(nil),
"policy_document": "",
"credential_type": iamUserCred,
"default_sts_ttl": int64(0),
"max_sts_ttl": int64(0),
"user_path": "",
}
if !reflect.DeepEqual(resp.Data, expected) {
return fmt.Errorf("bad: got: %#v\nexpected: %#v", resp.Data, expected)

View File

@ -6,6 +6,7 @@ import (
"encoding/json"
"errors"
"fmt"
"regexp"
"strings"
"time"
@ -16,6 +17,10 @@ import (
"github.com/hashicorp/vault/sdk/logical"
)
var (
userPathRegex = regexp.MustCompile(`^\/([\x21-\x7F]{0,510}\/)?$`)
)
func pathListRoles(b *backend) *framework.Path {
return &framework.Path{
Pattern: "roles/?$",
@ -89,6 +94,13 @@ or IAM role to assume`,
Description: "Deprecated; use policy_document instead. IAM policy document",
Deprecated: true,
},
"user_path": &framework.FieldSchema{
Type: framework.TypeString,
Description: "Path for IAM User. Only valid when credential_type is " + iamUserCred,
DisplayName: "User Path",
Default: "/",
},
},
Callbacks: map[logical.Operation]framework.OperationFunc{
@ -245,6 +257,20 @@ func (b *backend) pathRolesWrite(ctx context.Context, req *logical.Request, d *f
roleEntry.MaxSTSTTL = time.Duration(maxSTSTTLRaw.(int)) * time.Second
}
if userPathRaw, ok := d.GetOk("user_path"); ok {
if legacyRole != "" {
return logical.ErrorResponse("cannot supply deprecated role or policy parameters with user_path"), nil
}
if !strutil.StrListContains(roleEntry.CredentialTypes, iamUserCred) {
return logical.ErrorResponse(fmt.Sprintf("user_path parameter only valid for %s credential type", iamUserCred)), nil
}
if !userPathRegex.MatchString(userPathRaw.(string)) {
return logical.ErrorResponse(fmt.Sprintf("The specified value for user_path is invalid. It must match '%s' regexp", userPathRegex.String())), nil
}
roleEntry.UserPath = userPathRaw.(string)
}
if roleEntry.MaxSTSTTL > 0 &&
roleEntry.DefaultSTSTTL > 0 &&
roleEntry.DefaultSTSTTL > roleEntry.MaxSTSTTL {
@ -432,6 +458,7 @@ type awsRoleEntry struct {
Version int `json:"version"` // Version number of the role format
DefaultSTSTTL time.Duration `json:"default_sts_ttl"` // Default TTL for STS credentials
MaxSTSTTL time.Duration `json:"max_sts_ttl"` // Max allowed TTL for STS credentials
UserPath string `json:"user_path"` // The path for the IAM user when using "iam_user" credential type
}
func (r *awsRoleEntry) toResponseData() map[string]interface{} {
@ -442,7 +469,9 @@ func (r *awsRoleEntry) toResponseData() map[string]interface{} {
"policy_document": r.PolicyDocument,
"default_sts_ttl": int64(r.DefaultSTSTTL.Seconds()),
"max_sts_ttl": int64(r.MaxSTSTTL.Seconds()),
"user_path": r.UserPath,
}
if r.InvalidData != "" {
respData["invalid_data"] = r.InvalidData
}

View File

@ -4,6 +4,7 @@ import (
"context"
"reflect"
"strconv"
"strings"
"testing"
"github.com/hashicorp/vault/sdk/logical"
@ -154,3 +155,61 @@ func TestUpgradeLegacyPolicyEntry(t *testing.T) {
t.Fatalf("bad: expected %#v; received %#v", expected, *output)
}
}
func TestUserPathValidity(t *testing.T) {
testCases := []struct {
description string
userPath string
isValid bool
}{
{
description: "Default",
userPath: "/",
isValid: true,
},
{
description: "Empty",
userPath: "",
isValid: false,
},
{
description: "Valid",
userPath: "/path/",
isValid: true,
},
{
description: "Missing leading slash",
userPath: "path/",
isValid: false,
},
{
description: "Missing trailing slash",
userPath: "/path",
isValid: false,
},
{
description: "Invalid character",
userPath: "/šiauliai/",
isValid: false,
},
{
description: "Max length",
userPath: "/" + strings.Repeat("a", 510) + "/",
isValid: true,
},
{
description: "Too long",
userPath: "/" + strings.Repeat("a", 511) + "/",
isValid: false,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
if tc.isValid != userPathRegex.MatchString(tc.userPath) {
t.Fatalf("bad: expected %s", strconv.FormatBool(tc.isValid))
}
})
}
}

View File

@ -180,9 +180,15 @@ func (b *backend) secretAccessKeysCreate(
return nil, errwrap.Wrapf("error writing WAL entry: {{err}}", err)
}
userPath := role.UserPath
if userPath == "" {
userPath = "/"
}
// Create the user
_, err = iamClient.CreateUser(&iam.CreateUserInput{
UserName: aws.String(username),
Path: aws.String(userPath),
})
if err != nil {
if walErr := framework.DeleteWAL(ctx, s, walID); walErr != nil {

View File

@ -143,7 +143,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
}
}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Token Type | Replication | Seal Wrap | Options | Description"}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Token Type | Replication | Seal Wrap | Options | Description | UUID"}
for _, path := range paths {
mount := auths[path]
@ -160,7 +160,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
pluginName = mount.Config.PluginName
}
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %t | %v | %s",
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %s | %s | %t | %v | %s | %s",
path,
pluginName,
mount.Accessor,
@ -171,6 +171,7 @@ func (c *AuthListCommand) detailedMounts(auths map[string]*api.AuthMount) []stri
mount.SealWrap,
mount.Options,
mount.Description,
mount.UUID,
))
}

View File

@ -143,7 +143,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
}
}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Force No Cache | Replication | Seal Wrap | Options | Description"}
out := []string{"Path | Plugin | Accessor | Default TTL | Max TTL | Force No Cache | Replication | Seal Wrap | Options | Description | UUID "}
for _, path := range paths {
mount := mounts[path]
@ -160,7 +160,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
pluginName = mount.Config.PluginName
}
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s | %t | %v | %s",
out = append(out, fmt.Sprintf("%s | %s | %s | %s | %s | %t | %s | %t | %v | %s | %s",
path,
pluginName,
mount.Accessor,
@ -171,6 +171,7 @@ func (c *SecretsListCommand) detailedMounts(mounts map[string]*api.MountOutput)
mount.SealWrap,
mount.Options,
mount.Description,
mount.UUID,
))
}

12
go.mod
View File

@ -20,7 +20,6 @@ require (
github.com/aliyun/alibaba-cloud-sdk-go v0.0.0-20190412020505-60e2075261b6
github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5
github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2
github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 // indirect
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da
github.com/armon/go-proxyproto v0.0.0-20190211145416-68259f75880e
github.com/armon/go-radix v1.0.0
@ -37,10 +36,7 @@ require (
github.com/cockroachdb/apd v1.1.0 // indirect
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 // indirect
github.com/coreos/bbolt v1.3.2 // indirect
github.com/coreos/etcd v3.3.12+incompatible // indirect
github.com/coreos/go-semver v0.2.0
github.com/dancannon/gorethink v4.0.0+incompatible // indirect
github.com/denisenkom/go-mssqldb v0.0.0-20190412130859-3b1d194e553a
github.com/dnaeon/go-vcr v1.0.1 // indirect
github.com/docker/go-connections v0.4.0 // indirect
@ -49,11 +45,9 @@ require (
github.com/fatih/color v1.7.0
github.com/fatih/structs v1.1.0
github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa
github.com/garyburd/redigo v1.6.0 // indirect
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32
github.com/go-errors/errors v1.0.1
github.com/go-sql-driver/mysql v1.4.1
github.com/go-stomp/stomp v2.0.2+incompatible // indirect
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31
github.com/gocql/gocql v0.0.0-20190402132108-0e1d5de854df
github.com/golang/protobuf v1.3.1
@ -99,7 +93,6 @@ require (
github.com/kr/text v0.1.0
github.com/lib/pq v1.0.0
github.com/marstr/guid v1.1.0 // indirect
github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b // indirect
github.com/mattn/go-colorable v0.0.9
github.com/michaelklishin/rabbit-hole v1.5.0
github.com/mitchellh/cli v1.0.0
@ -113,11 +106,8 @@ require (
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v0.1.1 // indirect
github.com/opentracing/opentracing-go v1.1.0 // indirect
github.com/ory-am/common v0.4.0 // indirect
github.com/ory/dockertest v3.3.4+incompatible
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pborman/uuid v1.2.0 // indirect
github.com/pkg/errors v0.8.1
github.com/posener/complete v1.2.1
github.com/pquerna/otp v1.1.0
@ -136,9 +126,7 @@ require (
google.golang.org/api v0.3.2
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107
google.golang.org/grpc v1.20.0
gopkg.in/gorethink/gorethink.v4 v4.1.0 // indirect
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce
gopkg.in/ory-am/dockertest.v2 v2.2.3
gopkg.in/ory-am/dockertest.v3 v3.3.4
gopkg.in/square/go-jose.v2 v2.3.1
gotest.tools v2.2.0+incompatible // indirect

31
go.sum
View File

@ -37,8 +37,6 @@ github.com/aliyun/aliyun-oss-go-sdk v0.0.0-20190307165228-86c17b95fcd5/go.mod h1
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2 h1:VoHKYIXEQU5LWoambPBOvYxyLqZYHuj+rj5DVnMUc3k=
github.com/apple/foundationdb/bindings/go v0.0.0-20190411004307-cd5c9d91fad2/go.mod h1:OMVSB21p9+xQUIqlGizHPZfjK+SHws1ht+ZytVDoz9U=
github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61 h1:Xz25cuW4REGC5W5UtpMU3QItMIImag615HiQcRbxqKQ=
github.com/araddon/gou v0.0.0-20190110011759-c797efecbb61/go.mod h1:ikc1XA58M+Rx7SEbf0bLJCfBkwayZ8T5jBo5FXK8Uz8=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@ -65,7 +63,6 @@ github.com/boombuler/barcode v1.0.0 h1:s1TvRnXwL2xJRaccrdcBQMZxq6X7DvsMogtmJeHDd
github.com/boombuler/barcode v1.0.0/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/briankassouf/jose v0.9.2-0.20180619214549-d2569464773f h1:ZMEzE7R0WNqgbHplzSBaYJhJi5AZWTCK9baU0ebzG6g=
github.com/briankassouf/jose v0.9.2-0.20180619214549-d2569464773f/go.mod h1:HQhVmdUf7dBNwIIdBTivnCDxcf6IZY3/zrb+uKSJz6Y=
github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY=
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.0 h1:LzQXZOgg4CQfE6bFvXGM30YZL1WW/M337pXml+GrcZ4=
@ -85,10 +82,6 @@ github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c h1:2zRrJW
github.com/cockroachdb/cockroach-go v0.0.0-20181001143604-e0a95dfd547c/go.mod h1:XGLbWH/ujMcbPbhZq52Nv6UrCghb1yGn//133kEsvDk=
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808 h1:4BX8f882bXEDKfWIf0wa8HRvpnBoPszJJXL+TVbBw4M=
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.12+incompatible h1:pAWNwdf7QiT1zfaWyqCtNZQWCLByQyA3JrSQyuYAqnQ=
github.com/coreos/etcd v3.3.12+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-oidc v2.0.0+incompatible h1:+RStIopZ8wooMx+Vs5Bt8zMXxV1ABl5LbakNExNmZIg=
github.com/coreos/go-oidc v2.0.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
@ -97,8 +90,6 @@ github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5t
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf h1:CAKfRE2YtTUIjjh1bkBtyYFaUT/WmOqsJjgtihT0vMI=
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/dancannon/gorethink v4.0.0+incompatible h1:KFV7Gha3AuqT+gr0B/eKvGhbjmUv0qGF43aKCIKVE9A=
github.com/dancannon/gorethink v4.0.0+incompatible/go.mod h1:BLvkat9KmZc1efyYwhz3WnybhRZtgF1K929FD8z1avU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -139,8 +130,6 @@ github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7 h1:D2LrfOPgGHQprIx
github.com/gammazero/deque v0.0.0-20190130191400-2afb3858e9c7/go.mod h1:GeIq9qoE43YdGnDXURnmKTnGg15pQz4mYkXSTChbneI=
github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56 h1:VzbudKn/nvxYKOdzgkEBS6SSreRjAgoJ+ZeS4wPFkgc=
github.com/gammazero/workerpool v0.0.0-20190406235159-88d534f22b56/go.mod h1:w9RqFVO2BM3xwWEcAB8Fwp0OviTBBEiRmSBDfbXnd3w=
github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
@ -153,8 +142,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stomp/stomp v2.0.2+incompatible h1:0yPknMJh32lE2xiCFGW5t/KgamhUC4OgCv10wIjx5aw=
github.com/go-stomp/stomp v2.0.2+incompatible/go.mod h1:VqCtqNZv1226A1/79yh+rMiFUcfY3R109np+7ke4n0c=
github.com/go-test/deep v1.0.1 h1:UQhStjbkDClarlmv0am7OXXO4/GaPdCGiUiMTvi28sg=
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31 h1:28FVBuwkwowZMjbA7M0wXsI6t3PYulRTMio3SO+eKCM=
@ -350,8 +337,6 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/marstr/guid v1.1.0 h1:/M4H/1G4avsieL6BbUwCOBzulmoeKVP5ux/3mQNnbyI=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b h1:v29yPGHhOqw7VHEnTeQFAth3SsBrmwc8JfuhNY0G34k=
github.com/mattbaird/elastigo v0.0.0-20170123220020-2fe47fd29e4b/go.mod h1:5MWrJXKRQyhQdUCF+vu6U5c4nQpg70vW3eHaU0/AYbU=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
@ -410,13 +395,8 @@ github.com/opencontainers/image-spec v1.0.1 h1:JMemWkRwHx4Zj+fVxWoMCFm/8sYGGrUVo
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/opencontainers/runc v0.1.1 h1:GlxAyO6x8rfZYN9Tt0Kti5a/cP41iuiO2yYT0IJGY8Y=
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/openzipkin/zipkin-go v0.1.3/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
github.com/ory-am/common v0.4.0 h1:edGPoxYX4hno0IJHXh9TCMUPR6ZcJp+y6aClFYxeuUE=
github.com/ory-am/common v0.4.0/go.mod h1:oCYGuwwM8FyYMKqh9vrhBaeUoyz/edx0bgJN6uS6/+k=
github.com/ory/dockertest v3.3.4+incompatible h1:VrpM6Gqg7CrPm3bL4Wm1skO+zFWLbh7/Xb5kGEbJRh8=
github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
@ -425,8 +405,6 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
@ -478,7 +456,6 @@ github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24 h1:pntxY8Ary0t4
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/sirupsen/logrus v1.0.5 h1:8c8b5uO0zS4X6RPl/sd1ENwSkIc0/H2PaHxE3udaE8I=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0 h1:juTguoYk5qI21pwyTXY3B3Y5cOTH3ZUyZCg1v/mihuo=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
@ -527,7 +504,6 @@ go.uber.org/zap v1.9.1 h1:XCJQEf3W6eZaVwhRBof6ImoYGJSITeKWsyeh3HFu/5o=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4 h1:wviDUSmtheHRBfoY8B9U8ELl2USoXi2YFwdGdpIIkzI=
golang.org/x/crypto v0.0.0-20180608092829-8ac0e0d97ce4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@ -568,7 +544,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6 h1:bjcUS9ztw9kFmmIxJInhon/0Is3p+EHBKNgquIzo1OI=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180828065106-d99a578cf41b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs=
@ -635,13 +610,9 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/fatih/pool.v2 v2.0.0 h1:xIFeWtxifuQJGk/IEPKsTduEKcKvPmhoiVDGpC40nKg=
gopkg.in/fatih/pool.v2 v2.0.0/go.mod h1:8xVGeu1/2jr2wm5V9SPuMht2H5AEmf5aFMGSQixtjTY=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/gorethink/gorethink.v4 v4.1.0 h1:xoE9qJ9Ae9KdKEsiQGCF44u2JdnjyohrMBRDtts3Gjw=
gopkg.in/gorethink/gorethink.v4 v4.1.0/go.mod h1:M7JgwrUAmshJ3iUbEK0Pt049MPyPK+CYDGGaEjdZb/c=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
@ -649,8 +620,6 @@ gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk=
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce h1:xcEWjVhvbDy+nHP67nPDDpbYrY+ILlfndk4bRioVHaU=
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
gopkg.in/ory-am/dockertest.v2 v2.2.3 h1:vSYvP7tvyfAm9merq0gHmcI4yk5nkPpfXmoBCnSP3/4=
gopkg.in/ory-am/dockertest.v2 v2.2.3/go.mod h1:kDHEsan1UcKFYH1c28sDmqnmeqIpB4Nj682gSNhYDYM=
gopkg.in/ory-am/dockertest.v3 v3.3.4 h1:oen8RiwxVNxtQ1pRoV4e4jqh6UjNsOuIZ1NXns6jdcw=
gopkg.in/ory-am/dockertest.v3 v3.3.4/go.mod h1:s9mmoLkaGeAh97qygnNj4xWkiN7e1SKekYC6CovU+ek=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=

View File

@ -4,7 +4,6 @@ import (
"context"
"encoding/json"
"errors"
"github.com/go-test/deep"
"net/http"
"net/http/httptest"
"net/textproto"
@ -12,6 +11,8 @@ import (
"strings"
"testing"
"github.com/go-test/deep"
cleanhttp "github.com/hashicorp/go-cleanhttp"
"github.com/hashicorp/vault/helper/namespace"
"github.com/hashicorp/vault/sdk/helper/consts"
@ -375,8 +376,14 @@ func TestSysMounts_headerAuth(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); len(diff) > 0 {

View File

@ -62,8 +62,14 @@ func TestSysAuth(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if !reflect.DeepEqual(actual, expected) {
@ -156,8 +162,14 @@ func TestSysEnableAuth(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); diff != nil {
@ -227,8 +239,14 @@ func TestSysDisableAuth(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); diff != nil {

View File

@ -2,10 +2,11 @@ package http
import (
"encoding/json"
"github.com/go-test/deep"
"reflect"
"testing"
"github.com/go-test/deep"
"github.com/fatih/structs"
"github.com/hashicorp/vault/vault"
)
@ -134,8 +135,13 @@ func TestSysMounts(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); len(diff) > 0 {
@ -300,8 +306,13 @@ func TestSysMount(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); len(diff) > 0 {
@ -486,8 +497,13 @@ func TestSysRemount(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if !reflect.DeepEqual(actual, expected) {
@ -628,8 +644,13 @@ func TestSysUnmount(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); len(diff) > 0 {
@ -876,8 +897,13 @@ func TestSysTuneMount(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); len(diff) > 0 {
@ -1069,8 +1095,13 @@ func TestSysTuneMount(t *testing.T) {
if v.(map[string]interface{})["accessor"] == "" {
t.Fatalf("no accessor from %s", k)
}
if v.(map[string]interface{})["uuid"] == "" {
t.Fatalf("no uuid from %s", k)
}
expected[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["accessor"] = v.(map[string]interface{})["accessor"]
expected["data"].(map[string]interface{})[k].(map[string]interface{})["uuid"] = v.(map[string]interface{})["uuid"]
}
if diff := deep.Equal(actual, expected); len(diff) > 0 {

View File

@ -123,16 +123,13 @@ func NewMSSQLBackend(conf map[string]string, logger log.Logger) (physical.Backen
"') CREATE TABLE " + dbTable + " (Path VARCHAR(512) PRIMARY KEY, Value VARBINARY(MAX))"
if schema != "dbo" {
if _, err := db.Exec("USE " + database); err != nil {
return nil, errwrap.Wrapf("failed to switch mssql database: {{err}}", err)
}
var num int
err = db.QueryRow("SELECT 1 FROM sys.schemas WHERE name = '" + schema + "'").Scan(&num)
err = db.QueryRow("SELECT 1 FROM " + database + ".sys.schemas WHERE name = '" + schema + "'").Scan(&num)
switch {
case err == sql.ErrNoRows:
if _, err := db.Exec("CREATE SCHEMA " + schema); err != nil {
if _, err := db.Exec("USE " + database + "; EXEC ('CREATE SCHEMA " + schema + "')"); err != nil {
return nil, errwrap.Wrapf("failed to create mssql schema: {{err}}", err)
}

View File

@ -27,6 +27,11 @@ func TestMSSQLBackend(t *testing.T) {
table = "test"
}
schema := os.Getenv("MSSQL_SCHEMA")
if schema == "" {
schema = "test"
}
username := os.Getenv("MSSQL_USERNAME")
password := os.Getenv("MSSQL_PASSWORD")
@ -37,6 +42,59 @@ func TestMSSQLBackend(t *testing.T) {
"server": server,
"database": database,
"table": table,
"schema": schema,
"username": username,
"password": password,
}, logger)
if err != nil {
t.Fatalf("Failed to create new backend: %v", err)
}
defer func() {
mssql := b.(*MSSQLBackend)
_, err := mssql.client.Exec("DROP TABLE " + mssql.dbTable)
if err != nil {
t.Fatalf("Failed to drop table: %v", err)
}
}()
physical.ExerciseBackend(t, b)
physical.ExerciseBackend_ListPrefix(t, b)
}
func TestMSSQLBackend_schema(t *testing.T) {
server := os.Getenv("MSSQL_SERVER")
if server == "" {
t.SkipNow()
}
database := os.Getenv("MSSQL_DB")
if database == "" {
database = "test"
}
table := os.Getenv("MSSQL_TABLE")
if table == "" {
table = "test"
}
schema := os.Getenv("MSSQL_SCHEMA")
if schema == "" {
schema = "test"
}
username := os.Getenv("MSSQL_USERNAME")
password := os.Getenv("MSSQL_PASSWORD")
// Run vault tests
logger := logging.NewVaultLogger(log.Debug)
b, err := NewMSSQLBackend(map[string]string{
"server": server,
"database": database,
"schema": schema,
"table": table,
"username": username,
"password": password,
}, logger)

View File

@ -12,8 +12,8 @@ import (
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/helper/testhelpers"
vaulthttp "github.com/hashicorp/vault/http"
"github.com/hashicorp/vault/logical"
"github.com/hashicorp/vault/physical"
"github.com/hashicorp/vault/sdk/logical"
"github.com/hashicorp/vault/sdk/physical"
"github.com/hashicorp/vault/vault"
"github.com/kr/pretty"
)

View File

@ -661,6 +661,7 @@ func mountInfo(entry *MountEntry) map[string]interface{} {
"local": entry.Local,
"seal_wrap": entry.SealWrap,
"options": entry.Options,
"uuid": entry.UUID,
}
entryConfig := map[string]interface{}{
"default_lease_ttl": int64(entry.Config.DefaultLeaseTTL.Seconds()),

View File

@ -153,6 +153,7 @@ func TestSystemBackend_mounts(t *testing.T) {
"type": "kv",
"description": "key/value secret storage",
"accessor": resp.Data["secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -168,6 +169,7 @@ func TestSystemBackend_mounts(t *testing.T) {
"type": "system",
"description": "system endpoints used for control, policy and debugging",
"accessor": resp.Data["sys/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["sys/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -182,6 +184,7 @@ func TestSystemBackend_mounts(t *testing.T) {
"description": "per-token private secret storage",
"type": "cubbyhole",
"accessor": resp.Data["cubbyhole/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["cubbyhole/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -195,6 +198,7 @@ func TestSystemBackend_mounts(t *testing.T) {
"description": "identity store",
"type": "identity",
"accessor": resp.Data["identity/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["identity/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -246,6 +250,7 @@ func TestSystemBackend_mount(t *testing.T) {
"type": "kv",
"description": "key/value secret storage",
"accessor": resp.Data["secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -261,6 +266,7 @@ func TestSystemBackend_mount(t *testing.T) {
"type": "system",
"description": "system endpoints used for control, policy and debugging",
"accessor": resp.Data["sys/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["sys/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -275,6 +281,7 @@ func TestSystemBackend_mount(t *testing.T) {
"description": "per-token private secret storage",
"type": "cubbyhole",
"accessor": resp.Data["cubbyhole/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["cubbyhole/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -288,6 +295,7 @@ func TestSystemBackend_mount(t *testing.T) {
"description": "identity store",
"type": "identity",
"accessor": resp.Data["identity/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["identity/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -301,6 +309,7 @@ func TestSystemBackend_mount(t *testing.T) {
"description": "",
"type": "kv",
"accessor": resp.Data["prod/secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["prod/secret/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": int64(2100),
"max_lease_ttl": int64(2700),
@ -1441,6 +1450,7 @@ func TestSystemBackend_authTable(t *testing.T) {
"type": "token",
"description": "token based credentials",
"accessor": resp.Data["token/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["token/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": int64(0),
"max_lease_ttl": int64(0),
@ -1494,6 +1504,7 @@ func TestSystemBackend_enableAuth(t *testing.T) {
"type": "noop",
"description": "",
"accessor": resp.Data["foo/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["foo/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": int64(2100),
"max_lease_ttl": int64(2700),
@ -1508,6 +1519,7 @@ func TestSystemBackend_enableAuth(t *testing.T) {
"type": "token",
"description": "token based credentials",
"accessor": resp.Data["token/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["token/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": int64(0),
"max_lease_ttl": int64(0),
@ -2270,6 +2282,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"type": "kv",
"description": "key/value secret storage",
"accessor": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["secret/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -2285,6 +2298,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"type": "system",
"description": "system endpoints used for control, policy and debugging",
"accessor": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["sys/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -2299,6 +2313,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"description": "per-token private secret storage",
"type": "cubbyhole",
"accessor": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["cubbyhole/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -2312,6 +2327,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"description": "identity store",
"type": "identity",
"accessor": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["uuid"],
"config": map[string]interface{}{
"default_lease_ttl": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["config"].(map[string]interface{})["default_lease_ttl"].(int64),
"max_lease_ttl": resp.Data["secret"].(map[string]interface{})["identity/"].(map[string]interface{})["config"].(map[string]interface{})["max_lease_ttl"].(int64),
@ -2334,6 +2350,7 @@ func TestSystemBackend_InternalUIMounts(t *testing.T) {
"type": "token",
"description": "token based credentials",
"accessor": resp.Data["auth"].(map[string]interface{})["token/"].(map[string]interface{})["accessor"],
"uuid": resp.Data["auth"].(map[string]interface{})["token/"].(map[string]interface{})["uuid"],
"local": false,
"seal_wrap": false,
},

View File

@ -106,6 +106,10 @@ func (c *Core) reloadMatchingPlugin(ctx context.Context, pluginName string) erro
// reloadBackendCommon is a generic method to reload a backend provided a
// MountEntry.
func (c *Core) reloadBackendCommon(ctx context.Context, entry *MountEntry, isAuth bool) error {
// Make sure our cache is up-to-date. Since some singleton mounts can be
// tuned, we do this before the below check.
entry.SyncCache()
// We don't want to reload the singleton mounts. They often have specific
// inmemory elements and we don't want to touch them here.
if strutil.StrListContains(singletonMounts, entry.Type) {

View File

@ -2,12 +2,7 @@ package transit
import (
"context"
"encoding/base64"
"errors"
"fmt"
"os"
"path"
"strconv"
"strings"
"sync/atomic"
"time"
@ -15,7 +10,6 @@ import (
"github.com/armon/go-metrics"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/sdk/physical"
"github.com/hashicorp/vault/vault/seal"
)
@ -23,13 +17,8 @@ import (
// Seal is a seal that leverages Vault's Transit secret
// engine
type Seal struct {
logger log.Logger
client *api.Client
renewer *api.Renewer
mountPath string
keyName string
logger log.Logger
client transitClientEncryptor
currentKeyID *atomic.Value
}
@ -47,142 +36,16 @@ func NewSeal(logger log.Logger) *Seal {
// SetConfig processes the config info from the server config
func (s *Seal) SetConfig(config map[string]string) (map[string]string, error) {
if config == nil {
config = map[string]string{}
client, sealInfo, err := newTransitClient(s.logger, config)
if err != nil {
return nil, err
}
s.client = client
switch {
case os.Getenv("VAULT_TRANSIT_SEAL_MOUNT_PATH") != "":
s.mountPath = os.Getenv("VAULT_TRANSIT_SEAL_MOUNT_PATH")
case config["mount_path"] != "":
s.mountPath = config["mount_path"]
default:
return nil, fmt.Errorf("mount_path is required")
}
switch {
case os.Getenv("VAULT_TRANSIT_SEAL_KEY_NAME") != "":
s.keyName = os.Getenv("VAULT_TRANSIT_SEAL_KEY_NAME")
case config["key_name"] != "":
s.keyName = config["key_name"]
default:
return nil, fmt.Errorf("key_name is required")
}
var disableRenewal bool
var disableRenewalRaw string
switch {
case os.Getenv("VAULT_TRANSIT_SEAL_DISABLE_RENEWAL") != "":
disableRenewalRaw = os.Getenv("VAULT_TRANSIT_SEAL_DISABLE_RENEWAL")
case config["disable_renewal"] != "":
disableRenewalRaw = config["disable_renewal"]
}
if disableRenewalRaw != "" {
var err error
disableRenewal, err = strconv.ParseBool(disableRenewalRaw)
if err != nil {
return nil, err
}
}
var namespace string
switch {
case os.Getenv("VAULT_NAMESPACE") != "":
namespace = os.Getenv("VAULT_NAMESPACE")
case config["namespace"] != "":
namespace = config["namespace"]
}
apiConfig := api.DefaultConfig()
if config["address"] != "" {
apiConfig.Address = config["address"]
}
if config["tls_ca_cert"] != "" || config["tls_ca_path"] != "" || config["tls_client_cert"] != "" || config["tls_client_key"] != "" ||
config["tls_server_name"] != "" || config["tls_skip_verify"] != "" {
var tlsSkipVerify bool
if config["tls_skip_verify"] != "" {
var err error
tlsSkipVerify, err = strconv.ParseBool(config["tls_skip_verify"])
if err != nil {
return nil, err
}
}
tlsConfig := &api.TLSConfig{
CACert: config["tls_ca_cert"],
CAPath: config["tls_ca_path"],
ClientCert: config["tls_client_cert"],
ClientKey: config["tls_client_key"],
TLSServerName: config["tls_server_name"],
Insecure: tlsSkipVerify,
}
if err := apiConfig.ConfigureTLS(tlsConfig); err != nil {
return nil, err
}
}
if s.client == nil {
client, err := api.NewClient(apiConfig)
if err != nil {
return nil, err
}
if config["token"] != "" {
client.SetToken(config["token"])
}
if namespace != "" {
client.SetNamespace(namespace)
}
if client.Token() == "" {
return nil, errors.New("missing token")
}
s.client = client
// Send a value to test the seal and to set the current key id
if _, err := s.Encrypt(context.Background(), []byte("a")); err != nil {
return nil, err
}
if !disableRenewal {
// Renew the token immediately to get a secret to pass to renewer
secret, err := client.Auth().Token().RenewTokenAsSelf(s.client.Token(), 0)
// If we don't get an error renewing, set up a renewer. The token may not be renewable or not have
// permission to renew-self.
if err == nil {
renewer, err := s.client.NewRenewer(&api.RenewerInput{
Secret: secret,
})
if err != nil {
return nil, err
}
s.renewer = renewer
go func() {
for {
select {
case err := <-renewer.DoneCh():
s.logger.Info("shutting down token renewal")
if err != nil {
s.logger.Error("error renewing token", "error", err)
}
return
case <-renewer.RenewCh():
s.logger.Trace("successfully renewed token")
}
}
}()
go s.renewer.Renew()
} else {
s.logger.Info("unable to renew token, disabling renewal", "err", err)
}
}
}
sealInfo := make(map[string]string)
sealInfo["address"] = s.client.Address()
sealInfo["mount_path"] = s.mountPath
sealInfo["key_name"] = s.keyName
if namespace != "" {
sealInfo["namespace"] = namespace
// Send a value to test the seal and to set the current key id
if _, err := s.Encrypt(context.Background(), []byte("a")); err != nil {
client.Close()
return nil, err
}
return sealInfo, nil
@ -195,10 +58,7 @@ func (s *Seal) Init(_ context.Context) error {
// Finalize is called during shutdown
func (s *Seal) Finalize(_ context.Context) error {
if s.renewer != nil {
s.renewer.Stop()
}
s.client.Close()
return nil
}
@ -227,17 +87,12 @@ func (s *Seal) Encrypt(_ context.Context, plaintext []byte) (blob *physical.Encr
metrics.IncrCounter([]string{"seal", "encrypt"}, 1)
metrics.IncrCounter([]string{"seal", "transit", "encrypt"}, 1)
encPlaintext := base64.StdEncoding.EncodeToString(plaintext)
path := path.Join(s.mountPath, "encrypt", s.keyName)
secret, err := s.client.Logical().Write(path, map[string]interface{}{
"plaintext": encPlaintext,
})
ciphertext, err := s.client.Encrypt(plaintext)
if err != nil {
return nil, err
}
ciphertext := secret.Data["ciphertext"].(string)
splitKey := strings.Split(ciphertext, ":")
splitKey := strings.Split(string(ciphertext), ":")
if len(splitKey) != 3 {
return nil, errors.New("invalid ciphertext returned")
}
@ -245,7 +100,7 @@ func (s *Seal) Encrypt(_ context.Context, plaintext []byte) (blob *physical.Encr
s.currentKeyID.Store(keyID)
ret := &physical.EncryptedBlobInfo{
Ciphertext: []byte(ciphertext),
Ciphertext: ciphertext,
KeyInfo: &physical.SealKeyInfo{
KeyID: keyID,
},
@ -268,18 +123,9 @@ func (s *Seal) Decrypt(_ context.Context, in *physical.EncryptedBlobInfo) (pt []
metrics.IncrCounter([]string{"seal", "decrypt"}, 1)
metrics.IncrCounter([]string{"seal", "transit", "decrypt"}, 1)
path := path.Join(s.mountPath, "decrypt", s.keyName)
secret, err := s.client.Logical().Write(path, map[string]interface{}{
"ciphertext": string(in.Ciphertext),
})
plaintext, err := s.client.Decrypt(in.Ciphertext)
if err != nil {
return nil, err
}
plaintext, err := base64.StdEncoding.DecodeString(secret.Data["plaintext"].(string))
if err != nil {
return nil, err
}
return plaintext, nil
}

View File

@ -1,4 +1,4 @@
package transit
package transit_test
import (
"context"
@ -14,6 +14,7 @@ import (
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/helper/testhelpers/docker"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/vault/seal/transit"
"github.com/ory/dockertest"
)
@ -30,7 +31,7 @@ func TestTransitSeal_Lifecycle(t *testing.T) {
"mount_path": mountPath,
"key_name": keyName,
}
s := NewSeal(logging.NewVaultLogger(log.Trace))
s := transit.NewSeal(logging.NewVaultLogger(log.Trace))
_, err := s.SetConfig(sealConfig)
if err != nil {
t.Fatalf("error setting seal config: %v", err)
@ -87,7 +88,7 @@ func TestTransitSeal_TokenRenewal(t *testing.T) {
"mount_path": mountPath,
"key_name": keyName,
}
s := NewSeal(logging.NewVaultLogger(log.Trace))
s := transit.NewSeal(logging.NewVaultLogger(log.Trace))
_, err = s.SetConfig(sealConfig)
if err != nil {
t.Fatalf("error setting seal config: %v", err)

View File

@ -0,0 +1,203 @@
package transit
import (
"encoding/base64"
"errors"
"fmt"
"os"
"path"
"strconv"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/api"
)
type transitClientEncryptor interface {
Close()
Encrypt(plaintext []byte) (ciphertext []byte, err error)
Decrypt(ciphertext []byte) (plaintext []byte, err error)
}
type transitClient struct {
client *api.Client
renewer *api.Renewer
mountPath string
keyName string
}
func newTransitClient(logger log.Logger, config map[string]string) (*transitClient, map[string]string, error) {
if config == nil {
config = map[string]string{}
}
var mountPath, keyName string
switch {
case os.Getenv("VAULT_TRANSIT_SEAL_MOUNT_PATH") != "":
mountPath = os.Getenv("VAULT_TRANSIT_SEAL_MOUNT_PATH")
case config["mount_path"] != "":
mountPath = config["mount_path"]
default:
return nil, nil, fmt.Errorf("mount_path is required")
}
switch {
case os.Getenv("VAULT_TRANSIT_SEAL_KEY_NAME") != "":
keyName = os.Getenv("VAULT_TRANSIT_SEAL_KEY_NAME")
case config["key_name"] != "":
keyName = config["key_name"]
default:
return nil, nil, fmt.Errorf("key_name is required")
}
var disableRenewal bool
var disableRenewalRaw string
switch {
case os.Getenv("VAULT_TRANSIT_SEAL_DISABLE_RENEWAL") != "":
disableRenewalRaw = os.Getenv("VAULT_TRANSIT_SEAL_DISABLE_RENEWAL")
case config["disable_renewal"] != "":
disableRenewalRaw = config["disable_renewal"]
}
if disableRenewalRaw != "" {
var err error
disableRenewal, err = strconv.ParseBool(disableRenewalRaw)
if err != nil {
return nil, nil, err
}
}
var namespace string
switch {
case os.Getenv("VAULT_NAMESPACE") != "":
namespace = os.Getenv("VAULT_NAMESPACE")
case config["namespace"] != "":
namespace = config["namespace"]
}
apiConfig := api.DefaultConfig()
if config["address"] != "" {
apiConfig.Address = config["address"]
}
if config["tls_ca_cert"] != "" || config["tls_ca_path"] != "" || config["tls_client_cert"] != "" || config["tls_client_key"] != "" ||
config["tls_server_name"] != "" || config["tls_skip_verify"] != "" {
var tlsSkipVerify bool
if config["tls_skip_verify"] != "" {
var err error
tlsSkipVerify, err = strconv.ParseBool(config["tls_skip_verify"])
if err != nil {
return nil, nil, err
}
}
tlsConfig := &api.TLSConfig{
CACert: config["tls_ca_cert"],
CAPath: config["tls_ca_path"],
ClientCert: config["tls_client_cert"],
ClientKey: config["tls_client_key"],
TLSServerName: config["tls_server_name"],
Insecure: tlsSkipVerify,
}
if err := apiConfig.ConfigureTLS(tlsConfig); err != nil {
return nil, nil, err
}
}
apiClient, err := api.NewClient(apiConfig)
if err != nil {
return nil, nil, err
}
if config["token"] != "" {
apiClient.SetToken(config["token"])
}
if namespace != "" {
apiClient.SetNamespace(namespace)
}
if apiClient.Token() == "" {
return nil, nil, errors.New("missing token")
}
client := &transitClient{
client: apiClient,
mountPath: mountPath,
keyName: keyName,
}
if !disableRenewal {
// Renew the token immediately to get a secret to pass to renewer
secret, err := apiClient.Auth().Token().RenewTokenAsSelf(apiClient.Token(), 0)
// If we don't get an error renewing, set up a renewer. The token may not be renewable or not have
// permission to renew-self.
if err == nil {
renewer, err := apiClient.NewRenewer(&api.RenewerInput{
Secret: secret,
})
if err != nil {
return nil, nil, err
}
client.renewer = renewer
go func() {
for {
select {
case err := <-renewer.DoneCh():
logger.Info("shutting down token renewal")
if err != nil {
logger.Error("error renewing token", "error", err)
}
return
case <-renewer.RenewCh():
logger.Trace("successfully renewed token")
}
}
}()
go renewer.Renew()
} else {
logger.Info("unable to renew token, disabling renewal", "err", err)
}
}
sealInfo := make(map[string]string)
sealInfo["address"] = apiClient.Address()
sealInfo["mount_path"] = mountPath
sealInfo["key_name"] = keyName
if namespace != "" {
sealInfo["namespace"] = namespace
}
return client, sealInfo, nil
}
func (c *transitClient) Close() {
if c.renewer != nil {
c.renewer.Stop()
}
}
func (c *transitClient) Encrypt(plaintext []byte) ([]byte, error) {
encPlaintext := base64.StdEncoding.EncodeToString(plaintext)
path := path.Join(c.mountPath, "encrypt", c.keyName)
secret, err := c.client.Logical().Write(path, map[string]interface{}{
"plaintext": encPlaintext,
})
if err != nil {
return nil, err
}
return []byte(secret.Data["ciphertext"].(string)), nil
}
func (c *transitClient) Decrypt(ciphertext []byte) ([]byte, error) {
path := path.Join(c.mountPath, "decrypt", c.keyName)
secret, err := c.client.Logical().Write(path, map[string]interface{}{
"ciphertext": string(ciphertext),
})
if err != nil {
return nil, err
}
plaintext, err := base64.StdEncoding.DecodeString(secret.Data["plaintext"].(string))
if err != nil {
return nil, err
}
return plaintext, nil
}

View File

@ -0,0 +1,82 @@
package transit
import (
"context"
"errors"
"fmt"
"reflect"
"strings"
"testing"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/hashicorp/vault/sdk/physical"
"github.com/hashicorp/vault/vault/seal"
)
type testTransitClient struct {
keyID string
seal seal.Access
}
func newTestTransitClient(keyID string) *testTransitClient {
return &testTransitClient{
keyID: keyID,
seal: seal.NewTestSeal(nil),
}
}
func (m *testTransitClient) Close() {}
func (m *testTransitClient) Encrypt(plaintext []byte) ([]byte, error) {
v, err := m.seal.Encrypt(context.Background(), plaintext)
if err != nil {
return nil, err
}
return []byte(fmt.Sprintf("v1:%s:%s", m.keyID, string(v.Ciphertext))), nil
}
func (m *testTransitClient) Decrypt(ciphertext []byte) ([]byte, error) {
splitKey := strings.Split(string(ciphertext), ":")
if len(splitKey) != 3 {
return nil, errors.New("invalid ciphertext returned")
}
data := &physical.EncryptedBlobInfo{
Ciphertext: []byte(splitKey[2]),
}
v, err := m.seal.Decrypt(context.Background(), data)
if err != nil {
return nil, err
}
return v, nil
}
func TestTransitSeal_Lifecycle(t *testing.T) {
s := NewSeal(logging.NewVaultLogger(log.Trace))
keyID := "test-key"
s.client = newTestTransitClient(keyID)
// Test Encrypt and Decrypt calls
input := []byte("foo")
swi, err := s.Encrypt(context.Background(), input)
if err != nil {
t.Fatalf("err: %s", err.Error())
}
pt, err := s.Decrypt(context.Background(), swi)
if err != nil {
t.Fatalf("err: %s", err.Error())
}
if !reflect.DeepEqual(input, pt) {
t.Fatalf("expected %s, got %s", input, pt)
}
if s.KeyID() != keyID {
t.Fatalf("key id does not match: expected %s, got %s", keyID, s.KeyID())
}
}

View File

@ -1,9 +1,9 @@
language: go
go:
- 1.7
- 1.8
- 1.9
- "1.9"
- "1.10"
- "1.11"
before_install:
- go get github.com/mattn/goveralls

View File

@ -19,8 +19,9 @@ var (
// MaxDiff specifies the maximum number of differences to return.
MaxDiff = 10
// MaxDepth specifies the maximum levels of a struct to recurse into.
MaxDepth = 10
// MaxDepth specifies the maximum levels of a struct to recurse into,
// if greater than zero. If zero, there is no limit.
MaxDepth = 0
// LogErrors causes errors to be logged to STDERR when true.
LogErrors = false
@ -50,8 +51,9 @@ type cmp struct {
var errorType = reflect.TypeOf((*error)(nil)).Elem()
// Equal compares variables a and b, recursing into their structure up to
// MaxDepth levels deep, and returns a list of differences, or nil if there are
// none. Some differences may not be found if an error is also returned.
// MaxDepth levels deep (if greater than zero), and returns a list of differences,
// or nil if there are none. Some differences may not be found if an error is
// also returned.
//
// If a type has an Equal method, like time.Equal, it is called to check for
// equality.
@ -66,7 +68,7 @@ func Equal(a, b interface{}) []string {
if a == nil && b == nil {
return nil
} else if a == nil && b != nil {
c.saveDiff(b, "<nil pointer>")
c.saveDiff("<nil pointer>", b)
} else if a != nil && b == nil {
c.saveDiff(a, "<nil pointer>")
}
@ -82,7 +84,7 @@ func Equal(a, b interface{}) []string {
}
func (c *cmp) equals(a, b reflect.Value, level int) {
if level > MaxDepth {
if MaxDepth > 0 && level > MaxDepth {
logError(ErrMaxRecursion)
return
}
@ -140,16 +142,6 @@ func (c *cmp) equals(a, b reflect.Value, level int) {
return
}
// Types with an Equal(), like time.Time.
eqFunc := a.MethodByName("Equal")
if eqFunc.IsValid() {
retVals := eqFunc.Call([]reflect.Value{b})
if !retVals[0].Bool() {
c.saveDiff(a, b)
}
return
}
switch aKind {
/////////////////////////////////////////////////////////////////////
@ -167,6 +159,29 @@ func (c *cmp) equals(a, b reflect.Value, level int) {
Iterate through the fields (FirstName, LastName), recurse into their values.
*/
// Types with an Equal() method, like time.Time, only if struct field
// is exported (CanInterface)
if eqFunc := a.MethodByName("Equal"); eqFunc.IsValid() && eqFunc.CanInterface() {
// Handle https://github.com/go-test/deep/issues/15:
// Don't call T.Equal if the method is from an embedded struct, like:
// type Foo struct { time.Time }
// First, we'll encounter Equal(Ttime, time.Time) but if we pass b
// as the 2nd arg we'll panic: "Call using pkg.Foo as type time.Time"
// As far as I can tell, there's no way to see that the method is from
// time.Time not Foo. So we check the type of the 1st (0) arg and skip
// unless it's b type. Later, we'll encounter the time.Time anonymous/
// embedded field and then we'll have Equal(time.Time, time.Time).
funcType := eqFunc.Type()
if funcType.NumIn() == 1 && funcType.In(0) == bType {
retVals := eqFunc.Call([]reflect.Value{b})
if !retVals[0].Bool() {
c.saveDiff(a, b)
}
return
}
}
for i := 0; i < a.NumField(); i++ {
if aType.Field(i).PkgPath != "" && !CompareUnexportedFields {
continue // skip unexported field, e.g. s in type T struct {s string}

View File

@ -12,7 +12,7 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-test/deep v1.0.1/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=

View File

@ -159,6 +159,7 @@ type MountConfigInput struct {
}
type MountOutput struct {
UUID string `json:"uuid"`
Type string `json:"type"`
Description string `json:"description"`
Accessor string `json:"accessor"`

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2015 Ory GmbH & Aeneas Rekkas
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.

View File

@ -1,24 +0,0 @@
# ory-libs/env
Adds defaults to `os.GetEnv()` and saves you 3 lines of code:
```go
import "github.com/ory-am/common/env"
func main() {
port := env.Getenv("PORT", "80")
}
```
versus
```go
import "os"
func main() {
port := os.Getenv("PORT")
if port == "" {
port = "80"
}
}
```

View File

@ -1,13 +0,0 @@
// A very handy library which adds defaults to os.GetEnv()
package env
import "os"
// Getenv retrieves the value of the environment variable named by the key. It returns the value, which will return the fallback if the variable is not present.
func Getenv(key string, fallback string) string {
value := os.Getenv(key)
if value == "" {
return fallback
}
return value
}

View File

@ -1,10 +0,0 @@
language: go
go:
- "1.9"
- "1.10"
- "1.11"
- tip
script:
- go test -v ./...

View File

@ -1,10 +0,0 @@
# How to contribute
We definitely welcome patches and contribution to this project!
### Legal requirements
In order to protect both you and ourselves, you will need to sign the
[Contributor License Agreement](https://cla.developers.google.com/clas).
You may have already signed it for other Google projects.

View File

@ -1 +0,0 @@
Paul Borman <borman@google.com>

View File

@ -1,27 +0,0 @@
Copyright (c) 2009,2014 Google Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1,15 +0,0 @@
This project was automatically exported from code.google.com/p/go-uuid
# uuid ![build status](https://travis-ci.org/pborman/uuid.svg?branch=master)
The uuid package generates and inspects UUIDs based on [RFC 4122](http://tools.ietf.org/html/rfc4122) and DCE 1.1: Authentication and Security Services.
This package now leverages the github.com/google/uuid package (which is based off an earlier version of this package).
###### Install
`go get github.com/pborman/uuid`
###### Documentation
[![GoDoc](https://godoc.org/github.com/pborman/uuid?status.svg)](http://godoc.org/github.com/pborman/uuid)
Full `go doc` style documentation for the package can be viewed online without installing this package by using the GoDoc site here:
http://godoc.org/github.com/pborman/uuid

View File

@ -1,84 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
"fmt"
"os"
)
// A Domain represents a Version 2 domain
type Domain byte
// Domain constants for DCE Security (Version 2) UUIDs.
const (
Person = Domain(0)
Group = Domain(1)
Org = Domain(2)
)
// NewDCESecurity returns a DCE Security (Version 2) UUID.
//
// The domain should be one of Person, Group or Org.
// On a POSIX system the id should be the users UID for the Person
// domain and the users GID for the Group. The meaning of id for
// the domain Org or on non-POSIX systems is site defined.
//
// For a given domain/id pair the same token may be returned for up to
// 7 minutes and 10 seconds.
func NewDCESecurity(domain Domain, id uint32) UUID {
uuid := NewUUID()
if uuid != nil {
uuid[6] = (uuid[6] & 0x0f) | 0x20 // Version 2
uuid[9] = byte(domain)
binary.BigEndian.PutUint32(uuid[0:], id)
}
return uuid
}
// NewDCEPerson returns a DCE Security (Version 2) UUID in the person
// domain with the id returned by os.Getuid.
//
// NewDCEPerson(Person, uint32(os.Getuid()))
func NewDCEPerson() UUID {
return NewDCESecurity(Person, uint32(os.Getuid()))
}
// NewDCEGroup returns a DCE Security (Version 2) UUID in the group
// domain with the id returned by os.Getgid.
//
// NewDCEGroup(Group, uint32(os.Getgid()))
func NewDCEGroup() UUID {
return NewDCESecurity(Group, uint32(os.Getgid()))
}
// Domain returns the domain for a Version 2 UUID or false.
func (uuid UUID) Domain() (Domain, bool) {
if v, _ := uuid.Version(); v != 2 {
return 0, false
}
return Domain(uuid[9]), true
}
// Id returns the id for a Version 2 UUID or false.
func (uuid UUID) Id() (uint32, bool) {
if v, _ := uuid.Version(); v != 2 {
return 0, false
}
return binary.BigEndian.Uint32(uuid[0:4]), true
}
func (d Domain) String() string {
switch d {
case Person:
return "Person"
case Group:
return "Group"
case Org:
return "Org"
}
return fmt.Sprintf("Domain%d", int(d))
}

View File

@ -1,13 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// The uuid package generates and inspects UUIDs.
//
// UUIDs are based on RFC 4122 and DCE 1.1: Authentication and Security
// Services.
//
// This package is a partial wrapper around the github.com/google/uuid package.
// This package represents a UUID as []byte while github.com/google/uuid
// represents a UUID as [16]byte.
package uuid

View File

@ -1,3 +0,0 @@
module github.com/pborman/uuid
require github.com/google/uuid v1.0.0

View File

@ -1,2 +0,0 @@
github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=

View File

@ -1,53 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"crypto/md5"
"crypto/sha1"
"hash"
)
// Well known Name Space IDs and UUIDs
var (
NameSpace_DNS = Parse("6ba7b810-9dad-11d1-80b4-00c04fd430c8")
NameSpace_URL = Parse("6ba7b811-9dad-11d1-80b4-00c04fd430c8")
NameSpace_OID = Parse("6ba7b812-9dad-11d1-80b4-00c04fd430c8")
NameSpace_X500 = Parse("6ba7b814-9dad-11d1-80b4-00c04fd430c8")
NIL = Parse("00000000-0000-0000-0000-000000000000")
)
// NewHash returns a new UUID derived from the hash of space concatenated with
// data generated by h. The hash should be at least 16 byte in length. The
// first 16 bytes of the hash are used to form the UUID. The version of the
// UUID will be the lower 4 bits of version. NewHash is used to implement
// NewMD5 and NewSHA1.
func NewHash(h hash.Hash, space UUID, data []byte, version int) UUID {
h.Reset()
h.Write(space)
h.Write([]byte(data))
s := h.Sum(nil)
uuid := make([]byte, 16)
copy(uuid, s)
uuid[6] = (uuid[6] & 0x0f) | uint8((version&0xf)<<4)
uuid[8] = (uuid[8] & 0x3f) | 0x80 // RFC 4122 variant
return uuid
}
// NewMD5 returns a new MD5 (Version 3) UUID based on the
// supplied name space and data.
//
// NewHash(md5.New(), space, data, 3)
func NewMD5(space UUID, data []byte) UUID {
return NewHash(md5.New(), space, data, 3)
}
// NewSHA1 returns a new SHA1 (Version 5) UUID based on the
// supplied name space and data.
//
// NewHash(sha1.New(), space, data, 5)
func NewSHA1(space UUID, data []byte) UUID {
return NewHash(sha1.New(), space, data, 5)
}

View File

@ -1,85 +0,0 @@
// Copyright 2016 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"errors"
"fmt"
guuid "github.com/google/uuid"
)
// MarshalText implements encoding.TextMarshaler.
func (u UUID) MarshalText() ([]byte, error) {
if len(u) != 16 {
return nil, nil
}
var js [36]byte
encodeHex(js[:], u)
return js[:], nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (u *UUID) UnmarshalText(data []byte) error {
if len(data) == 0 {
return nil
}
id := Parse(string(data))
if id == nil {
return errors.New("invalid UUID")
}
*u = id
return nil
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (u UUID) MarshalBinary() ([]byte, error) {
return u[:], nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (u *UUID) UnmarshalBinary(data []byte) error {
if len(data) == 0 {
return nil
}
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
var id [16]byte
copy(id[:], data)
*u = id[:]
return nil
}
// MarshalText implements encoding.TextMarshaler.
func (u Array) MarshalText() ([]byte, error) {
var js [36]byte
encodeHex(js[:], u[:])
return js[:], nil
}
// UnmarshalText implements encoding.TextUnmarshaler.
func (u *Array) UnmarshalText(data []byte) error {
id, err := guuid.ParseBytes(data)
if err != nil {
return err
}
*u = Array(id)
return nil
}
// MarshalBinary implements encoding.BinaryMarshaler.
func (u Array) MarshalBinary() ([]byte, error) {
return u[:], nil
}
// UnmarshalBinary implements encoding.BinaryUnmarshaler.
func (u *Array) UnmarshalBinary(data []byte) error {
if len(data) != 16 {
return fmt.Errorf("invalid UUID (got %d bytes)", len(data))
}
copy(u[:], data)
return nil
}

View File

@ -1,50 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
guuid "github.com/google/uuid"
)
// NodeInterface returns the name of the interface from which the NodeID was
// derived. The interface "user" is returned if the NodeID was set by
// SetNodeID.
func NodeInterface() string {
return guuid.NodeInterface()
}
// SetNodeInterface selects the hardware address to be used for Version 1 UUIDs.
// If name is "" then the first usable interface found will be used or a random
// Node ID will be generated. If a named interface cannot be found then false
// is returned.
//
// SetNodeInterface never fails when name is "".
func SetNodeInterface(name string) bool {
return guuid.SetNodeInterface(name)
}
// NodeID returns a slice of a copy of the current Node ID, setting the Node ID
// if not already set.
func NodeID() []byte {
return guuid.NodeID()
}
// SetNodeID sets the Node ID to be used for Version 1 UUIDs. The first 6 bytes
// of id are used. If id is less than 6 bytes then false is returned and the
// Node ID is not set.
func SetNodeID(id []byte) bool {
return guuid.SetNodeID(id)
}
// NodeID returns the 6 byte node id encoded in uuid. It returns nil if uuid is
// not valid. The NodeID is only well defined for version 1 and 2 UUIDs.
func (uuid UUID) NodeID() []byte {
if len(uuid) != 16 {
return nil
}
node := make([]byte, 6)
copy(node, uuid[10:])
return node
}

View File

@ -1,68 +0,0 @@
// Copyright 2015 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"database/sql/driver"
"errors"
"fmt"
)
// Scan implements sql.Scanner so UUIDs can be read from databases transparently
// Currently, database types that map to string and []byte are supported. Please
// consult database-specific driver documentation for matching types.
func (uuid *UUID) Scan(src interface{}) error {
switch src.(type) {
case string:
// if an empty UUID comes from a table, we return a null UUID
if src.(string) == "" {
return nil
}
// see uuid.Parse for required string format
parsed := Parse(src.(string))
if parsed == nil {
return errors.New("Scan: invalid UUID format")
}
*uuid = parsed
case []byte:
b := src.([]byte)
// if an empty UUID comes from a table, we return a null UUID
if len(b) == 0 {
return nil
}
// assumes a simple slice of bytes if 16 bytes
// otherwise attempts to parse
if len(b) == 16 {
parsed := make([]byte, 16)
copy(parsed, b)
*uuid = UUID(parsed)
} else {
u := Parse(string(b))
if u == nil {
return errors.New("Scan: invalid UUID format")
}
*uuid = u
}
default:
return fmt.Errorf("Scan: unable to scan type %T into UUID", src)
}
return nil
}
// Value implements sql.Valuer so that UUIDs can be written to databases
// transparently. Currently, UUIDs map to strings. Please consult
// database-specific driver documentation for matching types.
func (uuid UUID) Value() (driver.Value, error) {
return uuid.String(), nil
}

View File

@ -1,57 +0,0 @@
// Copyright 2014 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"encoding/binary"
guuid "github.com/google/uuid"
)
// A Time represents a time as the number of 100's of nanoseconds since 15 Oct
// 1582.
type Time = guuid.Time
// GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and
// clock sequence as well as adjusting the clock sequence as needed. An error
// is returned if the current time cannot be determined.
func GetTime() (Time, uint16, error) { return guuid.GetTime() }
// ClockSequence returns the current clock sequence, generating one if not
// already set. The clock sequence is only used for Version 1 UUIDs.
//
// The uuid package does not use global static storage for the clock sequence or
// the last time a UUID was generated. Unless SetClockSequence a new random
// clock sequence is generated the first time a clock sequence is requested by
// ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated
// for
func ClockSequence() int { return guuid.ClockSequence() }
// SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to
// -1 causes a new sequence to be generated.
func SetClockSequence(seq int) { guuid.SetClockSequence(seq) }
// Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
// uuid. It returns false if uuid is not valid. The time is only well defined
// for version 1 and 2 UUIDs.
func (uuid UUID) Time() (Time, bool) {
if len(uuid) != 16 {
return 0, false
}
time := int64(binary.BigEndian.Uint32(uuid[0:4]))
time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
return Time(time), true
}
// ClockSequence returns the clock sequence encoded in uuid. It returns false
// if uuid is not valid. The clock sequence is only well defined for version 1
// and 2 UUIDs.
func (uuid UUID) ClockSequence() (int, bool) {
if len(uuid) != 16 {
return 0, false
}
return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true
}

View File

@ -1,32 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
// xvalues returns the value of a byte as a hexadecimal digit or 255.
var xvalues = [256]byte{
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 10, 11, 12, 13, 14, 15, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
}
// xtob converts the the first two hex bytes of x into a byte.
func xtob(x string) (byte, bool) {
b1 := xvalues[x[0]]
b2 := xvalues[x[1]]
return (b1 << 4) | b2, b1 != 255 && b2 != 255
}

View File

@ -1,162 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
"bytes"
"crypto/rand"
"encoding/hex"
"io"
guuid "github.com/google/uuid"
)
// Array is a pass-by-value UUID that can be used as an effecient key in a map.
type Array [16]byte
// UUID converts uuid into a slice.
func (uuid Array) UUID() UUID {
return uuid[:]
}
// String returns the string representation of uuid,
// xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.
func (uuid Array) String() string {
return guuid.UUID(uuid).String()
}
// A UUID is a 128 bit (16 byte) Universal Unique IDentifier as defined in RFC
// 4122.
type UUID []byte
// A Version represents a UUIDs version.
type Version = guuid.Version
// A Variant represents a UUIDs variant.
type Variant = guuid.Variant
// Constants returned by Variant.
const (
Invalid = guuid.Invalid // Invalid UUID
RFC4122 = guuid.RFC4122 // The variant specified in RFC4122
Reserved = guuid.Reserved // Reserved, NCS backward compatibility.
Microsoft = guuid.Microsoft // Reserved, Microsoft Corporation backward compatibility.
Future = guuid.Future // Reserved for future definition.
)
var rander = rand.Reader // random function
// New returns a new random (version 4) UUID as a string. It is a convenience
// function for NewRandom().String().
func New() string {
return NewRandom().String()
}
// Parse decodes s into a UUID or returns nil. See github.com/google/uuid for
// the formats parsed.
func Parse(s string) UUID {
gu, err := guuid.Parse(s)
if err == nil {
return gu[:]
}
return nil
}
// ParseBytes is like Parse, except it parses a byte slice instead of a string.
func ParseBytes(b []byte) (UUID, error) {
gu, err := guuid.ParseBytes(b)
if err == nil {
return gu[:], nil
}
return nil, err
}
// Equal returns true if uuid1 and uuid2 are equal.
func Equal(uuid1, uuid2 UUID) bool {
return bytes.Equal(uuid1, uuid2)
}
// Array returns an array representation of uuid that can be used as a map key.
// Array panics if uuid is not valid.
func (uuid UUID) Array() Array {
if len(uuid) != 16 {
panic("invalid uuid")
}
var a Array
copy(a[:], uuid)
return a
}
// String returns the string form of uuid, xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
// , or "" if uuid is invalid.
func (uuid UUID) String() string {
if len(uuid) != 16 {
return ""
}
var buf [36]byte
encodeHex(buf[:], uuid)
return string(buf[:])
}
// URN returns the RFC 2141 URN form of uuid,
// urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, or "" if uuid is invalid.
func (uuid UUID) URN() string {
if len(uuid) != 16 {
return ""
}
var buf [36 + 9]byte
copy(buf[:], "urn:uuid:")
encodeHex(buf[9:], uuid)
return string(buf[:])
}
func encodeHex(dst []byte, uuid UUID) {
hex.Encode(dst[:], uuid[:4])
dst[8] = '-'
hex.Encode(dst[9:13], uuid[4:6])
dst[13] = '-'
hex.Encode(dst[14:18], uuid[6:8])
dst[18] = '-'
hex.Encode(dst[19:23], uuid[8:10])
dst[23] = '-'
hex.Encode(dst[24:], uuid[10:])
}
// Variant returns the variant encoded in uuid. It returns Invalid if
// uuid is invalid.
func (uuid UUID) Variant() Variant {
if len(uuid) != 16 {
return Invalid
}
switch {
case (uuid[8] & 0xc0) == 0x80:
return RFC4122
case (uuid[8] & 0xe0) == 0xc0:
return Microsoft
case (uuid[8] & 0xe0) == 0xe0:
return Future
default:
return Reserved
}
}
// Version returns the version of uuid. It returns false if uuid is not
// valid.
func (uuid UUID) Version() (Version, bool) {
if len(uuid) != 16 {
return 0, false
}
return Version(uuid[6] >> 4), true
}
// SetRand sets the random number generator to r, which implements io.Reader.
// If r.Read returns an error when the package requests random data then
// a panic will be issued.
//
// Calling SetRand with nil sets the random number generator to the default
// generator.
func SetRand(r io.Reader) {
guuid.SetRand(r)
}

View File

@ -1,23 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import (
guuid "github.com/google/uuid"
)
// NewUUID returns a Version 1 UUID based on the current NodeID and clock
// sequence, and the current time. If the NodeID has not been set by SetNodeID
// or SetNodeInterface then it will be set automatically. If the NodeID cannot
// be set NewUUID returns nil. If clock sequence has not been set by
// SetClockSequence then it will be set automatically. If GetTime fails to
// return the current NewUUID returns nil.
func NewUUID() UUID {
gu, err := guuid.NewUUID()
if err == nil {
return UUID(gu[:])
}
return nil
}

View File

@ -1,26 +0,0 @@
// Copyright 2011 Google Inc. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package uuid
import guuid "github.com/google/uuid"
// Random returns a Random (Version 4) UUID or panics.
//
// The strength of the UUIDs is based on the strength of the crypto/rand
// package.
//
// A note about uniqueness derived from the UUID Wikipedia entry:
//
// Randomly generated UUIDs have 122 random bits. One's annual risk of being
// hit by a meteorite is estimated to be one chance in 17 billion, that
// means the probability is about 0.00000000006 (6 × 1011),
// equivalent to the odds of creating a few tens of trillions of UUIDs in a
// year and having one duplicate.
func NewRandom() UUID {
if gu, err := guuid.NewRandom(); err == nil {
return UUID(gu[:])
}
return nil
}

View File

@ -1,6 +0,0 @@
.idea/
node_modules/
*.iml
*.exe
.cover/
vendor/

View File

@ -1,29 +0,0 @@
sudo: required
language: go
services:
- docker
env:
- DOCKER_BIND_LOCALHOST=true GO15VENDOREXPERIMENT=1
go:
- 1.4
- 1.5
- 1.6
- tip
matrix:
allow_failures:
- go: tip
- go: 1.4
install:
- go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/Masterminds/glide
- glide install
script:
- go vet -x .
- gotestcover -coverprofile="cover.out" -race -covermode="count" .
- goveralls -coverprofile="cover.out"

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2014 The Camlistore 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.

View File

@ -1,295 +0,0 @@
# [ory.am](https://ory.am)/dockertest
[![Build Status](https://travis-ci.org/ory-am/dockertest.svg)](https://travis-ci.org/ory-am/dockertest?branch=master)
[![Coverage Status](https://coveralls.io/repos/ory-am/dockertest/badge.svg?branch=master&service=github)](https://coveralls.io/github/ory-am/dockertest?branch=master)
Use Docker to run your Go language integration tests against third party services on **Microsoft Windows, Mac OSX and Linux**!
Dockertest uses [Docker](https://www.docker.com/toolbox) to spin up images on Windows and Mac OSX as well.
Dockertest is based on [docker.go](https://github.com/camlistore/camlistore/blob/master/pkg/test/dockertest/docker.go)
from [camlistore](https://github.com/camlistore/camlistore).
Dockertest currently supports these backends:
* PostgreSQL
* MySQL
* MongoDB
* NSQ
* Redis
* Elastic Search
* RethinkDB
* RabbitMQ
* Mockserver
* ActiveMQ
* ZooKeeper
* Cassandra
* Etcd
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
**Table of Contents**
- [Why should I use Dockertest?](#why-should-i-use-dockertest)
- [Installing and using Dockertest](#installing-and-using-dockertest)
- [Start a container](#start-a-container)
- [Write awesome tests](#write-awesome-tests)
- [Setting up Travis-CI](#setting-up-travis-ci)
- [Troubleshoot & FAQ](#troubleshoot-&-faq)
- [I need to use a specific container version for XYZ](#i-need-to-use-a-specific-container-version-for-xyz)
- [My build is broken!](#my-build-is-broken)
- [Out of disk space](#out-of-disk-space)
- [I am using docker machine (OSX / Linux)](#i-am-using-docker-machine-osx--linux)
- [Removing old containers](#removing-old-containers)
- [Customized database](#customized-database)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Why should I use Dockertest?
When developing applications, it is often necessary to use services that talk to a database system.
Unit Testing these services can be cumbersome because mocking database/DBAL is strenuous. Making slight changes to the
schema implies rewriting at least some, if not all of the mocks. The same goes for API changes in the DBAL.
To avoid this, it is smarter to test these specific services against a real database that is destroyed after testing.
Docker is the perfect system for running unit tests as you can spin up containers in a few seconds and kill them when
the test completes. The Dockertest library provides easy to use commands for spinning up Docker containers and using
them for your tests.
## Installing and using Dockertest
Using Dockertest is straightforward and simple. Check the [releases tab](https://github.com/ory-am/dockertest/releases)
for available releases.
To install dockertest, run
```
go get gopkg.in/ory-am/dockertest.vX
```
where `X` is your desired version. For example:
```
go get gopkg.in/ory-am/dockertest.v2
```
**Note:**
When using the Docker Toolbox (Windows / OSX), make sure that the VM is started by running `docker-machine start default`.
### Start a container
```go
package main
import (
"gopkg.in/ory-am/dockertest.v2"
"gopkg.in/mgo.v2"
"time"
)
func main() {
var db *mgo.Session
c, err := dockertest.ConnectToMongoDB(15, time.Millisecond*500, func(url string) bool {
// This callback function checks if the image's process is responsive.
// Sometimes, docker images are booted but the process (in this case MongoDB) is still doing maintenance
// before being fully responsive which might cause issues like "TCP Connection reset by peer".
var err error
db, err = mgo.Dial(url)
if err != nil {
return false
}
// Sometimes, dialing the database is not enough because the port is already open but the process is not responsive.
// Most database conenctors implement a ping function which can be used to test if the process is responsive.
// Alternatively, you could execute a query to see if an error occurs or not.
return db.Ping() == nil
})
if err != nil {
log.Fatalf("Could not connect to database: %s", err)
}
// Close db connection and kill the container when we leave this function body.
defer db.Close()
defer c.KillRemove()
// The image is now responsive.
}
```
You can start PostgreSQL and MySQL in a similar fashion.
There are some cases where it's useful to test how your application/code handles
remote resources failing / shutting down. For example, what if your database
goes offline? Does your application handle it gracefully?
This can be tested by stopping and starting an existing container:
```go
var hosts []string
c, err := ConnectToZooKeeper(15, time.Millisecond*500, func(url string) bool {
conn, _, err := zk.Connect([]string{url}, time.Second)
if err != nil {
return false
}
defer conn.Close()
hosts = []string{url}
return true
})
defer c.KillRemove()
conn, _, _ := zk.Connect(hosts, time.Second)
conn.Create("/test", []byte("hello"), 0, zk.WorldACL(zk.PermAll))
c.Stop()
_, _, err = zk.Get("/test") // err == zk.ErrNoServer
c.Start()
data, _, _ = zk.Get("/test") // data == []byte("hello")
```
It is also possible to start a custom container (in this example, a RabbitMQ container):
```go
c, ip, port, err := dockertest.SetupCustomContainer("rabbitmq", 5672, 10*time.Second)
if err != nil {
log.Fatalf("Could not setup container: %s", err
}
defer c.KillRemove()
err = dockertest.ConnectToCustomContainer(fmt.Sprintf("%v:%v", ip, port), 15, time.Millisecond*500, func(url string) bool {
amqp, err := amqp.Dial(fmt.Sprintf("amqp://%v", url))
if err != nil {
return false
}
defer amqp.Close()
return true
})
...
```
## Write awesome tests
It is a good idea to start up the container only once when running tests.
```go
import (
"fmt"
"testing"
"log"
"os"
"database/sql"
_ "github.com/lib/pq"
"gopkg.in/ory-am/dockertest.v2"
)
var db *sql.DB
func TestMain(m *testing.M) {
c, err := dockertest.ConnectToPostgreSQL(15, time.Second, func(url string) bool {
// Check if postgres is responsive...
var err error
db, err = sql.Open("postgres", url)
if err != nil {
return false
}
return db.Ping() == nil
})
if err != nil {
log.Fatalf("Could not connect to database: %s", err)
}
// Execute tasks like setting up schemata.
// Run tests
result := m.Run()
// Close database connection.
db.Close()
// Clean up image.
c.KillRemove()
// Exit tests.
os.Exit(result)
}
func TestFunction(t *testing.T) {
// db.Exec(...
}
```
### Setting up Travis-CI
You can run the Docker integration on Travis easily:
```yml
# Sudo is required for docker
sudo: required
# Enable docker
services:
- docker
# In Travis, we need to bind to 127.0.0.1 in order to get a working connection. This environment variable
# tells dockertest to do that.
env:
- DOCKERTEST_BIND_LOCALHOST=true
```
## Troubleshoot & FAQ
### I need to use a specific container version for XYZ
You can specify a container version by setting environment variables or globals. For more information, check [vars.go](vars.go).
### My build is broken!
With v2, we removed all `Open*` methods to reduce duplicate code, unnecessary dependencies and make maintenance easier.
If you relied on these, run `go get gopkg.in/ory-am/dockertest.v1` and replace
`import "github.com/ory-am/dockertest"` with `import "gopkg.in/ory-am/dockertest.v1"`.
### Out of disk space
Try cleaning up the images with [docker-cleanup-volumes](https://github.com/chadoe/docker-cleanup-volumes).
### I am using docker machine (OSX / Linux)
First of all, consider upgrading! If that's not an option, there are some steps you need to take:
* Set `dockertest.UseDockerMachine = "1"` or set the environment variable `DOCKERTEST_LEGACY_DOCKER_MACHINE=1`
* Set `docker.BindDockerToLocalhost = ""` or alternatively `DOCKER_BIND_LOCALHOST=`
### Removing old containers
Sometimes container clean up fails. Check out
[this stackoverflow question](http://stackoverflow.com/questions/21398087/how-to-delete-dockers-images) on how to fix this.
### Customized database
I am using postgres (or mysql) driver, how do I use customized database instead of default one?
You can alleviate this helper function to do that, see testcase or example below:
```go
func TestMain(m *testing.M) {
if c, err := dockertest.ConnectToPostgreSQL(15, time.Second, func(url string) bool {
customizedDB := "cherry" // here I am connecting cherry database
newURL, err := SetUpPostgreDatabase(customizedDB, url)
// or use SetUpMysqlDatabase for mysql driver
if err != nil {
log.Fatal(err)
}
db, err := sql.Open("postgres", newURL)
if err != nil {
return false
}
return db.Ping() == nil
}); err != nil {
log.Fatal(err)
}
```

View File

@ -1,43 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupActiveMQContainer sets up a real ActiveMQ instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupActiveMQContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 61613)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(ActiveMQImageName, port, 10*time.Second, func() (string, error) {
res, err := run("--name", GenerateContainerID(), "-d", "-P", "-p", forward, ActiveMQImageName)
return res, err
})
return
}
// ConnectToActiveMQ starts a ActiveMQ image and passes the amqp url to the connector callback.
// The url will match the ip:port pattern (e.g. 123.123.123.123:4241)
func ConnectToActiveMQ(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupActiveMQContainer()
if err != nil {
return c, fmt.Errorf("Could not set up ActiveMQ container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up ActiveMQ container.")
}

View File

@ -1,47 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupCassandraContainer sets up a real Cassandra node for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupCassandraContainer(versionTag string, optionalParams ...string) (c ContainerID, ip string, port int, err error) {
port = RandomPort()
// Forward for the CQL port.
forward := fmt.Sprintf("%d:%d", port, 9042)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
imageName := fmt.Sprintf("%s:%s", CassandraImageName, versionTag)
c, ip, err = SetupContainer(imageName, port, 10*time.Second, func() (string, error) {
return run(append(optionalParams, "--name", GenerateContainerID(), "-d", "-p", forward, imageName)...)
})
return
}
// ConnectToCassandra starts a Cassandra image and passes the nodes connection string to the connector callback function.
// The connection string will match the ip:port pattern, where port is the mapped CQL port.
func ConnectToCassandra(versionTag string, tries int, delay time.Duration, connector func(url string) bool, optionalParams ...string) (c ContainerID, err error) {
c, ip, port, err := SetupCassandraContainer(versionTag, optionalParams...)
if err != nil {
return c, fmt.Errorf("Could not setup Cassandra container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not setup Cassandra container.")
}

View File

@ -1,95 +0,0 @@
package dockertest
import (
"encoding/json"
"errors"
"fmt"
"log"
"time"
)
var (
// ConsulDatacenter must be defined when starting a Consul datacenter; this
// value will be used for both the datacenter and the ACL datacenter
ConsulDatacenter = "test"
// ConsulACLDefaultPolicy defines the default policy to use with Consul ACLs
ConsulACLDefaultPolicy = "deny"
// ConsulACLMasterToken defines the master ACL token
ConsulACLMasterToken = "test"
// A function with no arguments that outputs a valid JSON string to be used
// as the value of the environment variable CONSUL_LOCAL_CONFIG.
ConsulLocalConfigGen = DefaultConsulLocalConfig
)
func DefaultConsulLocalConfig() (string, error) {
type d struct {
Datacenter string `json:"datacenter,omitempty"`
ACLDatacenter string `json:"acl_datacenter,omitempty"`
ACLDefaultPolicy string `json:"acl_default_policy,omitempty"`
ACLMasterToken string `json:"acl_master_token,omitempty"`
}
vals := &d{
Datacenter: ConsulDatacenter,
ACLDatacenter: ConsulDatacenter,
ACLDefaultPolicy: ConsulACLDefaultPolicy,
ACLMasterToken: ConsulACLMasterToken,
}
ret, err := json.Marshal(vals)
if err != nil {
return "", err
}
return string(ret), nil
}
// SetupConsulContainer sets up a real Consul instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupConsulContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 8500)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
localConfig, err := ConsulLocalConfigGen()
if err != nil {
return "", "", 0, err
}
c, ip, err = SetupContainer(ConsulImageName, port, 15*time.Second, func() (string, error) {
return run(
"--name", GenerateContainerID(),
"-d",
"-p", forward,
"-e", fmt.Sprintf("CONSUL_LOCAL_CONFIG=%s", localConfig),
ConsulImageName,
"agent",
"-dev", // Run in dev mode
"-client", "0.0.0.0", // Allow clients from any IP, otherwise the bridge IP will be where clients come from and it will be rejected
)
})
return
}
// ConnectToConsul starts a Consul image and passes the address to the
// connector callback function.
func ConnectToConsul(tries int, delay time.Duration, connector func(address string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupConsulContainer()
if err != nil {
return c, fmt.Errorf("Could not set up Consul container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
address := fmt.Sprintf("%s:%d", ip, port)
if connector(address) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up Consul container.")
}

View File

@ -1,90 +0,0 @@
package dockertest
import (
"fmt"
"net"
"os/exec"
"strings"
"time"
)
// AwaitReachable tries to make a TCP connection to addr regularly.
// It returns an error if it's unable to make a connection before maxWait.
func AwaitReachable(addr string, maxWait time.Duration) error {
done := time.Now().Add(maxWait)
for time.Now().Before(done) {
c, err := net.Dial("tcp", addr)
if err == nil {
c.Close()
return nil
}
time.Sleep(100 * time.Millisecond)
}
return fmt.Errorf("%v unreachable for %v", addr, maxWait)
}
// ContainerID represents a container and offers methods like Kill or IP.
type ContainerID string
// IP retrieves the container's IP address.
func (c ContainerID) IP() (string, error) {
return IP(string(c))
}
// Kill runs "docker kill" on the container.
func (c ContainerID) Kill() error {
return KillContainer(string(c))
}
// Start runs "docker start" on the container.
func (c ContainerID) Start() error {
return StartContainer(string(c))
}
// Stop runs "docker stop" on the container.
func (c ContainerID) Stop() error {
return StopContainer(string(c))
}
// Remove runs "docker rm" on the container
func (c ContainerID) Remove() error {
if Debug || c == "nil" {
return nil
}
return runDockerCommand("docker", "rm", "-v", string(c)).Run()
}
// KillRemove calls Kill on the container, and then Remove if there was
// no error.
func (c ContainerID) KillRemove() error {
if err := c.Kill(); err != nil {
return err
}
return c.Remove()
}
// lookup retrieves the ip address of the container, and tries to reach
// before timeout the tcp address at this ip and given port.
func (c ContainerID) lookup(ports []int, timeout time.Duration) (ip string, err error) {
if DockerMachineAvailable {
var out []byte
out, err = exec.Command("docker-machine", "ip", DockerMachineName).Output()
ip = strings.TrimSpace(string(out))
} else if BindDockerToLocalhost != "" {
ip = "127.0.0.1"
} else {
ip, err = c.IP()
}
if err != nil {
err = fmt.Errorf("error getting IP: %v", err)
return
}
for _, port := range ports {
addr := fmt.Sprintf("%s:%d", ip, port)
err = AwaitReachable(addr, timeout)
if err != nil {
return
}
}
return
}

View File

@ -1,39 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupCustomContainer sets up a real an instance of the given image for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupCustomContainer(imageName string, exposedPort int, timeOut time.Duration, extraDockerArgs ...string) (c ContainerID, ip string, localPort int, err error) {
localPort = RandomPort()
forward := fmt.Sprintf("%d:%d", localPort, exposedPort)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(imageName, localPort, timeOut, func() (string, error) {
args := make([]string, 0, len(extraDockerArgs)+7)
args = append(args, "--name", GenerateContainerID(), "-d", "-P", "-p", forward)
args = append(args, extraDockerArgs...)
args = append(args, imageName)
return run(args...)
})
return
}
// ConnectToCustomContainer attempts to connect to a custom container until successful or the maximum number of tries is reached.
func ConnectToCustomContainer(url string, tries int, delay time.Duration, connector func(url string) bool) error {
for try := 0; try <= tries; try++ {
time.Sleep(delay)
if connector(url) {
return nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return errors.New("Could not set up custom container.")
}

View File

@ -1,5 +0,0 @@
// Package dockertest contains helper functions for setting up and tearing down docker containers to aid in testing.
// dockertest supports spinning up MySQL, PostgreSQL and MongoDB out of the box.
//
// Dockertest provides two environment variables
package dockertest

View File

@ -1,276 +0,0 @@
package dockertest
/*
Copyright 2014 The Camlistore 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.
*/
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log"
"math/rand"
"os/exec"
"regexp"
"strings"
"time"
// Import postgres driver
_ "github.com/lib/pq"
"github.com/pborman/uuid"
)
/// runLongTest checks all the conditions for running a docker container
// based on image.
func runLongTest(image string) error {
DockerMachineAvailable = false
if haveDockerMachine() && UseDockerMachine != "" {
DockerMachineAvailable = true
if !startDockerMachine() {
log.Printf(`Starting docker machine "%s" failed.
This could be because the image is already running or because the image does not exist.
Tests will fail if the image does not exist.`, DockerMachineName)
}
} else if !haveDocker() {
return errors.New("Neither 'docker' nor 'docker-machine' available on this system.")
}
if ok, err := HaveImage(image); !ok || err != nil {
if err != nil {
return fmt.Errorf("Error checking for docker image %s: %v", image, err)
}
log.Printf("Pulling docker image %s ...", image)
if err := Pull(image); err != nil {
return fmt.Errorf("Error pulling %s: %v", image, err)
}
}
return nil
}
func runDockerCommand(command string, args ...string) *exec.Cmd {
if DockerMachineAvailable {
command = "/usr/local/bin/" + strings.Join(append([]string{command}, args...), " ")
cmd := exec.Command("docker-machine", "ssh", DockerMachineName, command)
return cmd
}
return exec.Command(command, args...)
}
// haveDockerMachine returns whether the "docker" command was found.
func haveDockerMachine() bool {
_, err := exec.LookPath("docker-machine")
return err == nil
}
// startDockerMachine starts the docker machine and returns false if the command failed to execute
func startDockerMachine() bool {
_, err := exec.Command("docker-machine", "start", DockerMachineName).Output()
return err == nil
}
// haveDocker returns whether the "docker" command was found.
func haveDocker() bool {
_, err := exec.LookPath("docker")
return err == nil
}
type dockerImage struct {
repo string
tag string
}
type dockerImageList []dockerImage
func (l dockerImageList) contains(repo string, tag string) bool {
if tag == "" {
tag = "latest"
}
for _, image := range l {
if image.repo == repo && image.tag == tag {
return true
}
}
return false
}
func parseDockerImagesOutput(data []byte) (images dockerImageList) {
lines := strings.Split(string(data), "\n")
if len(lines) < 2 {
return
}
// skip first line with columns names
images = make(dockerImageList, 0, len(lines)-1)
for _, line := range lines[1:] {
cols := strings.Fields(line)
if len(cols) < 2 {
continue
}
image := dockerImage{
repo: cols[0],
tag: cols[1],
}
images = append(images, image)
}
return
}
func parseImageName(name string) (repo string, tag string) {
if fields := strings.SplitN(name, ":", 2); len(fields) == 2 {
repo, tag = fields[0], fields[1]
} else {
repo = name
}
return
}
// HaveImage reports if docker have image 'name'.
func HaveImage(name string) (bool, error) {
out, err := runDockerCommand("docker", "images", "--no-trunc").Output()
if err != nil {
return false, err
}
repo, tag := parseImageName(name)
images := parseDockerImagesOutput(out)
return images.contains(repo, tag), nil
}
func run(args ...string) (containerID string, err error) {
var stdout, stderr bytes.Buffer
validID := regexp.MustCompile(`^([a-zA-Z0-9]+)$`)
cmd := runDockerCommand("docker", append([]string{"run"}, args...)...)
cmd.Stdout, cmd.Stderr = &stdout, &stderr
if err = cmd.Run(); err != nil {
err = fmt.Errorf("Error running docker\nStdOut: %s\nStdErr: %s\nError: %v\n\n", stdout.String(), stderr.String(), err)
return
}
containerID = strings.TrimSpace(string(stdout.String()))
if !validID.MatchString(containerID) {
return "", fmt.Errorf("Error running docker: %s", containerID)
}
if containerID == "" {
return "", errors.New("Unexpected empty output from `docker run`")
}
return containerID, nil
}
// KillContainer runs docker kill on a container.
func KillContainer(container string) error {
if container != "" {
return runDockerCommand("docker", "kill", container).Run()
}
return nil
}
// StartContainer runs 'docker start' on a container.
func StartContainer(container string) error {
if container != "" {
return runDockerCommand("docker", "start", container).Run()
}
return nil
}
// StopContainer runs 'docker stop' on a container.
func StopContainer(container string) error {
if container != "" {
return runDockerCommand("docker", "stop", container).Run()
}
return nil
}
// Pull retrieves the docker image with 'docker pull'.
func Pull(image string) error {
out, err := runDockerCommand("docker", "pull", image).CombinedOutput()
if err != nil {
err = fmt.Errorf("%v: %s", err, out)
}
return err
}
// IP returns the IP address of the container.
func IP(containerID string) (string, error) {
out, err := runDockerCommand("docker", "inspect", containerID).Output()
if err != nil {
return "", err
}
type networkSettings struct {
IPAddress string
}
type container struct {
NetworkSettings networkSettings
}
var c []container
if err := json.NewDecoder(bytes.NewReader(out)).Decode(&c); err != nil {
return "", err
}
if len(c) == 0 {
return "", errors.New("no output from docker inspect")
}
if ip := c[0].NetworkSettings.IPAddress; ip != "" {
return ip, nil
}
return "", errors.New("could not find an IP. Not running?")
}
// SetupMultiportContainer sets up a container, using the start function to run the given image.
// It also looks up the IP address of the container, and tests this address with the given
// ports and timeout. It returns the container ID and its IP address, or makes the test
// fail on error.
func SetupMultiportContainer(image string, ports []int, timeout time.Duration, start func() (string, error)) (c ContainerID, ip string, err error) {
err = runLongTest(image)
if err != nil {
return "", "", err
}
containerID, err := start()
if err != nil {
return "", "", err
}
c = ContainerID(containerID)
ip, err = c.lookup(ports, timeout)
if err != nil {
c.KillRemove()
return "", "", err
}
return c, ip, nil
}
// SetupContainer sets up a container, using the start function to run the given image.
// It also looks up the IP address of the container, and tests this address with the given
// port and timeout. It returns the container ID and its IP address, or makes the test
// fail on error.
func SetupContainer(image string, port int, timeout time.Duration, start func() (string, error)) (c ContainerID, ip string, err error) {
return SetupMultiportContainer(image, []int{port}, timeout, start)
}
// RandomPort returns a random non-priviledged port.
func RandomPort() int {
min := 1025
max := 65534
return min + rand.Intn(max-min)
}
// GenerateContainerID generated a random container id.
func GenerateContainerID() string {
return ContainerPrefix + uuid.New()
}
func init() {
rand.Seed(time.Now().UTC().UnixNano())
}

View File

@ -1,42 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupElasticSearchContainer sets up a real ElasticSearch instance for testing purposes
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupElasticSearchContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 9200)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(ElasticSearchImageName, port, 15*time.Second, func() (string, error) {
return run("--name", GenerateContainerID(), "-d", "-P", "-p", forward, ElasticSearchImageName)
})
return
}
// ConnectToElasticSearch starts an ElasticSearch image and passes the database url to the connector callback function.
// The url will match the ip:port pattern (e.g. 123.123.123.123:4241)
func ConnectToElasticSearch(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupElasticSearchContainer()
if err != nil {
return c, fmt.Errorf("Could not set up ElasticSearch container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up ElasticSearch container.")
}

View File

@ -1,52 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupEtcdContainer sets up a real etcd instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupEtcdContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 2379)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(EtcdImageName, port, 10*time.Second, func() (string, error) {
return run(
"--name", GenerateContainerID(),
"-d",
"-p", forward,
EtcdImageName,
"etcd",
"-name", "etcd-test",
"-advertise-client-urls", "http://127.0.0.1:2379",
"-listen-client-urls", "http://0.0.0.0:2379", // Allow clients from any IP
)
})
return c, ip, port, err
}
// ConnectToEtcd starts a etcd image and passes the address to the
// connector callback function.
func ConnectToEtcd(tries int, delay time.Duration, connector func(address string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupEtcdContainer()
if err != nil {
return c, fmt.Errorf("Could not set up etcd container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
address := fmt.Sprintf("%s:%d", ip, port)
if connector(address) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up etcd container.")
}

View File

@ -1,149 +0,0 @@
hash: ea1ce82416f8736cf3fd1f562146f135ee5071c7aed0dcbb4e33b4c18cdeaf6d
updated: 2016-09-03T10:56:05.944984255+08:00
imports:
- name: github.com/go-errors/errors
version: a41850380601eeb43f4350f7d17c6bbd8944aaf8
- name: github.com/go-sql-driver/mysql
version: 0b58b37b664c21f3010e836f1b931e1d0b0b0685
- name: github.com/lib/pq
version: 50761b0867bd1d9d069276790bcd4a3bccf2324a
subpackages:
- oid
- name: github.com/ory-am/common
version: d93c852f2d09c219fd058756caf67bbdf8cf4be4
subpackages:
- env
- name: github.com/pborman/uuid
version: a97ce2ca70fa5a848076093f05e639a89ca34d06
testImports:
- name: github.com/araddon/gou
version: 4060436435c0b91885cb45241edb764c632ed8ae
- name: github.com/bitly/go-hostpool
version: d0e59c22a56e8dadfed24f74f452cea5a52722d2
- name: github.com/cenk/backoff
version: cdf48bbc1eb78d1349cbda326a4a037f7ba565c6
- name: github.com/cloudfoundry-incubator/candiedyaml
version: 99c3df83b51532e3615f851d8c2dbb638f5313bf
- name: github.com/coreos/etcd
version: 5695120efcfdc05b8ba51be2018d99c2937b41d0
subpackages:
- auth/authpb
- clientv3
- etcdserver/api/v3rpc/rpctypes
- etcdserver/etcdserverpb
- mvcc/mvccpb
- pkg/tlsutil
- name: github.com/dancannon/gorethink
version: 27d3045458910e2fc56025a0b52caaaa96414a26
- name: github.com/davecgh/go-spew
version: 6cf5744a041a0022271cefed95ba843f6d87fd51
subpackages:
- spew
- name: github.com/garyburd/redigo
version: 8873b2f1995f59d4bcdd2b0dc9858e2cb9bf0c13
subpackages:
- internal
- redis
- name: github.com/ghodss/yaml
version: aa0c862057666179de291b67d9f093d12b5a8473
- name: github.com/go-stomp/stomp
version: 364e36fe21291dd5aec3cba10ea15b0e654d9b40
subpackages:
- frame
- name: github.com/gocql/gocql
version: 3ac1aabebaf2705c6f695d4ef2c25ab6239e88b3
subpackages:
- internal/lru
- internal/murmur
- internal/streams
- name: github.com/golang/protobuf
version: 1f49d83d9aa00e6ce4fc8258c71cc7786aec968a
subpackages:
- jsonpb
- proto
- name: github.com/golang/snappy
version: d9eb7a3d35ec988b8585d4a0068e462c27d28380
- name: github.com/grpc-ecosystem/grpc-gateway
version: 331418a167bc76e7e4e7469cf704033eddaba7a5
subpackages:
- runtime
- runtime/internal
- utilities
- name: github.com/hailocab/go-hostpool
version: e80d13ce29ede4452c43dea11e79b9bc8a15b478
- name: github.com/hashicorp/consul
version: 0047f09be55fdf790263cbc088bf5ec924ffe644
subpackages:
- api
- name: github.com/hashicorp/go-cleanhttp
version: ad28ea4487f05916463e2423a55166280e8254b5
- name: github.com/hashicorp/serf
version: 9432bc08aa8d486e497e27f84878ebbe8c1eab66
subpackages:
- coordinate
- name: github.com/mattbaird/elastigo
version: 34c4c4d8425cbdcbc8e257943a2044d5e9f7dab5
subpackages:
- lib
- name: github.com/pmezard/go-difflib
version: 792786c7400a136282c1664665ae0a8db921c6c2
subpackages:
- difflib
- name: github.com/samuel/go-zookeeper
version: 8c6a1d79a44d2742da3660540d1fd43f4ddcfc8c
subpackages:
- zk
- name: github.com/Sirupsen/logrus
version: 3ec0642a7fb6488f65b06f9040adc67e3990296a
- name: github.com/streadway/amqp
version: 2e25825abdbd7752ff08b270d313b93519a0a232
- name: github.com/stretchr/testify
version: f390dcf405f7b83c997eac1b06768bb9f44dec18
subpackages:
- assert
- require
- name: golang.org/x/crypto
version: f160b6bf95857cd862817875dd958be022e587c4
subpackages:
- pbkdf2
- name: golang.org/x/net
version: 1358eff22f0dd0c54fc521042cc607f6ff4b531a
subpackages:
- context
- http2
- http2/hpack
- internal/timeseries
- lex/httplex
- trace
- name: golang.org/x/sys
version: a646d33e2ee3172a661fc09bca23bb4889a41bc8
subpackages:
- unix
- name: google.golang.org/grpc
version: 52f6504dc290bd928a8139ba94e3ab32ed9a6273
subpackages:
- codes
- credentials
- grpclog
- internal
- metadata
- naming
- peer
- transport
- name: gopkg.in/dancannon/gorethink.v2
version: e75f34b0817d1ed1a4b967975ccf5fac9535dbc2
subpackages:
- encoding
- ql2
- types
- name: gopkg.in/fatih/pool.v2
version: 20a0a429c5f93de45c90f5f09ea297c25e0929b3
- name: gopkg.in/inf.v0
version: 3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4
- name: gopkg.in/mgo.v2
version: 3f83fa5005286a7fe593b055f0d7771a7dce4655
subpackages:
- bson
- internal/json
- internal/sasl
- internal/scram

View File

@ -1,39 +0,0 @@
package: github.com/ory-am/dockertest
import:
- package: github.com/go-errors/errors
- package: github.com/go-sql-driver/mysql
version: 0b58b37b664c21f3010e836f1b931e1d0b0b0685
- package: github.com/lib/pq
- package: github.com/ory-am/common
subpackages:
- env
- package: github.com/pborman/uuid
version: ~1.0.0
testImport:
- package: github.com/dancannon/gorethink
version: ~2.1.3
- package: github.com/garyburd/redigo
version: ~1.0.0
subpackages:
- redis
- package: github.com/go-stomp/stomp
version: 364e36fe21291dd5aec3cba10ea15b0e654d9b40
- package: github.com/gocql/gocql
- package: github.com/hashicorp/consul
version: ~0.7.0-test2
subpackages:
- api
- package: github.com/mattbaird/elastigo
version: 34c4c4d8425cbdcbc8e257943a2044d5e9f7dab5
subpackages:
- lib
- package: github.com/samuel/go-zookeeper
subpackages:
- zk
- package: github.com/streadway/amqp
- package: github.com/stretchr/testify
version: ~1.1.3
subpackages:
- assert
- require
- package: gopkg.in/mgo.v2

View File

@ -1,66 +0,0 @@
package dockertest
import (
"fmt"
"github.com/go-errors/errors"
"log"
"time"
)
// SetupMockserverContainer sets up a real Mockserver instance for testing purposes
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupMockserverContainer() (c ContainerID, ip string, mockPort, proxyPort int, err error) {
mockPort = RandomPort()
proxyPort = RandomPort()
mockForward := fmt.Sprintf("%d:%d", mockPort, 1080)
proxyForward := fmt.Sprintf("%d:%d", proxyPort, 1090)
if BindDockerToLocalhost != "" {
mockForward = "127.0.0.1:" + mockForward
proxyForward = "127.0.0.1:" + proxyForward
}
c, ip, err = SetupMultiportContainer(RabbitMQImageName, []int{mockPort, proxyPort}, 10*time.Second, func() (string, error) {
res, err := run("--name", GenerateContainerID(), "-d", "-P", "-p", mockForward, "-p", proxyForward, MockserverImageName)
return res, err
})
return
}
// ConnectToMockserver starts a Mockserver image and passes the mock and proxy urls to the connector callback functions.
// The urls will match the http://ip:port pattern (e.g. http://123.123.123.123:4241)
func ConnectToMockserver(tries int, delay time.Duration, mockConnector func(url string) bool, proxyConnector func(url string) bool) (c ContainerID, err error) {
c, ip, mockPort, proxyPort, err := SetupMockserverContainer()
if err != nil {
return c, fmt.Errorf("Could not set up Mockserver container: %v", err)
}
var mockOk, proxyOk bool
for try := 0; try <= tries; try++ {
time.Sleep(delay)
if !mockOk {
if mockConnector(fmt.Sprintf("http://%s:%d", ip, mockPort)) {
mockOk = true
} else {
log.Printf("Try %d failed for mock. Retrying.", try)
}
}
if !proxyOk {
if proxyConnector(fmt.Sprintf("http://%s:%d", ip, proxyPort)) {
proxyOk = true
} else {
log.Printf("Try %d failed for proxy. Retrying.", try)
}
}
}
if mockOk && proxyOk {
return c, nil
} else {
return c, errors.New("Could not set up Mockserver container.")
}
}

View File

@ -1,43 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupMongoContainer sets up a real MongoDB instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupMongoContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 27017)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(MongoDBImageName, port, 10*time.Second, func() (string, error) {
res, err := run("--name", GenerateContainerID(), "-d", "-P", "-p", forward, MongoDBImageName)
return res, err
})
return
}
// ConnectToMongoDB starts a MongoDB image and passes the database url to the connector callback.
// The url will match the ip:port pattern (e.g. 123.123.123.123:4241)
func ConnectToMongoDB(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupMongoContainer()
if err != nil {
return c, fmt.Errorf("Could not set up MongoDB container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up MongoDB container.")
}

View File

@ -1,75 +0,0 @@
package dockertest
import (
"database/sql"
"errors"
"fmt"
"log"
"time"
mysql "github.com/go-sql-driver/mysql"
)
const (
defaultMySQLDBName = "mysql"
)
// SetupMySQLContainer sets up a real MySQL instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupMySQLContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 3306)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(MySQLImageName, port, 10*time.Second, func() (string, error) {
return run("--name", GenerateContainerID(), "-d", "-p", forward, "-e", fmt.Sprintf("MYSQL_ROOT_PASSWORD=%s", MySQLPassword), MySQLImageName)
})
return
}
// ConnectToMySQL starts a MySQL image and passes the database url to the connector callback function.
// The url will match the username:password@tcp(ip:port) pattern (e.g. `root:root@tcp(123.123.123.123:3131)`)
func ConnectToMySQL(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupMySQLContainer()
if err != nil {
return c, fmt.Errorf("Could not set up MySQL container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%s@tcp(%s:%d)/mysql?parseTime=true", MySQLUsername, MySQLPassword, ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up MySQL container.")
}
// SetUpMySQLDatabase connects mysql container with given $connectURL and also creates a new database named $databaseName
// A modified url used to connect the created database will be returned
func SetUpMySQLDatabase(databaseName, connectURL string) (url string, err error) {
if databaseName == defaultMySQLDBName {
return connectURL, nil
}
db, err := sql.Open("mysql", connectURL)
if err != nil {
return "", err
}
defer db.Close()
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", databaseName))
if err != nil {
return "", err
}
// parse dsn
config, err := mysql.ParseDSN(connectURL)
if err != nil {
return "", err
}
config.DBName = databaseName // overwrite database name
return config.FormatDSN(), nil
}

View File

@ -1,90 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupNSQdContainer sets up a real NSQ instance for testing purposes
// using a Docker container and executing `/nsqd`. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupNSQdContainer() (c ContainerID, ip string, tcpPort int, httpPort int, err error) {
// --name nsqd -p 4150:4150 -p 4151:4151 nsqio/nsq /nsqd --broadcast-address=192.168.99.100 --lookupd-tcp-address=192.168.99.100:4160
tcpPort = RandomPort()
httpPort = RandomPort()
tcpForward := fmt.Sprintf("%d:%d", tcpPort, 4150)
if BindDockerToLocalhost != "" {
tcpForward = "127.0.0.1:" + tcpForward
}
httpForward := fmt.Sprintf("%d:%d", httpPort, 4151)
if BindDockerToLocalhost != "" {
httpForward = "127.0.0.1:" + httpForward
}
c, ip, err = SetupContainer(NSQImageName, tcpPort, 15*time.Second, func() (string, error) {
return run("--name", GenerateContainerID(), "-d", "-P", "-p", tcpForward, "-p", httpForward, NSQImageName, "/nsqd", fmt.Sprintf("--broadcast-address=%s", ip), fmt.Sprintf("--lookupd-tcp-address=%s:4160", ip))
})
return
}
// SetupNSQLookupdContainer sets up a real NSQ instance for testing purposes
// using a Docker container and executing `/nsqlookupd`. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupNSQLookupdContainer() (c ContainerID, ip string, tcpPort int, httpPort int, err error) {
// docker run --name lookupd -p 4160:4160 -p 4161:4161 nsqio/nsq /nsqlookupd
tcpPort = RandomPort()
httpPort = RandomPort()
tcpForward := fmt.Sprintf("%d:%d", tcpPort, 4160)
if BindDockerToLocalhost != "" {
tcpForward = "127.0.0.1:" + tcpForward
}
httpForward := fmt.Sprintf("%d:%d", httpPort, 4161)
if BindDockerToLocalhost != "" {
httpForward = "127.0.0.1:" + httpForward
}
c, ip, err = SetupContainer(NSQImageName, tcpPort, 15*time.Second, func() (string, error) {
return run("--name", GenerateContainerID(), "-d", "-P", "-p", tcpForward, "-p", httpForward, NSQImageName, "/nsqlookupd")
})
return
}
// ConnectToNSQLookupd starts a NSQ image with `/nsqlookupd` running and passes the IP, HTTP port, and TCP port to the connector callback function.
// The url will match the ip pattern (e.g. 123.123.123.123).
func ConnectToNSQLookupd(tries int, delay time.Duration, connector func(ip string, httpPort int, tcpPort int) bool) (c ContainerID, err error) {
c, ip, tcpPort, httpPort, err := SetupNSQLookupdContainer()
if err != nil {
return c, fmt.Errorf("Could not set up NSQLookupd container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
if connector(ip, httpPort, tcpPort) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up NSQLookupd container.")
}
// ConnectToNSQd starts a NSQ image with `/nsqd` running and passes the IP, HTTP port, and TCP port to the connector callback function.
// The url will match the ip pattern (e.g. 123.123.123.123).
func ConnectToNSQd(tries int, delay time.Duration, connector func(ip string, httpPort int, tcpPort int) bool) (c ContainerID, err error) {
c, ip, tcpPort, httpPort, err := SetupNSQdContainer()
if err != nil {
return c, fmt.Errorf("Could not set up NSQd container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
if connector(ip, httpPort, tcpPort) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up NSQd container.")
}

View File

@ -1,80 +0,0 @@
package dockertest
import (
"database/sql"
"errors"
"fmt"
"log"
"net/url"
"time"
_ "github.com/lib/pq"
)
// SetupPostgreSQLContainer sets up a real PostgreSQL instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupPostgreSQLContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 5432)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(PostgresImageName, port, 15*time.Second, func() (string, error) {
return run("--name", GenerateContainerID(), "-d", "-p", forward, "-e", fmt.Sprintf("POSTGRES_PASSWORD=%s", PostgresPassword), PostgresImageName)
})
return
}
// ConnectToPostgreSQL starts a PostgreSQL image and passes the database url to the connector callback.
func ConnectToPostgreSQL(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupPostgreSQLContainer()
if err != nil {
return c, fmt.Errorf("Could not set up PostgreSQL container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("postgres://%s:%s@%s:%d/postgres?sslmode=disable", PostgresUsername, PostgresPassword, ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up PostgreSQL container.")
}
// SetUpPostgreDatabase connects postgre container with given $connectURL and also creates a new database named $databaseName
// A modified url used to connect the created database will be returned
func SetUpPostgreDatabase(databaseName, connectURL string) (modifiedURL string, err error) {
db, err := sql.Open("postgres", connectURL)
if err != nil {
return "", err
}
defer db.Close()
count := 0
err = db.QueryRow(
fmt.Sprintf("SELECT COUNT(*) FROM pg_catalog.pg_database WHERE datname = '%s' ;", databaseName)).
Scan(&count)
if err != nil {
return "", err
}
if count == 0 {
// not found for $databaseName, create it
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", databaseName))
if err != nil {
return "", err
}
}
// replace dbname in url
// from: postgres://postgres:docker@192.168.99.100:9071/postgres?sslmode=disable
// to: postgres://postgres:docker@192.168.99.100:9071/$databaseName?sslmode=disable
u, err := url.Parse(connectURL)
if err != nil {
return "", err
}
u.Path = fmt.Sprintf("/%s", databaseName)
return u.String(), nil
}

View File

@ -1,43 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupRabbitMQContainer sets up a real RabbitMQ instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupRabbitMQContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 5672)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(RabbitMQImageName, port, 10*time.Second, func() (string, error) {
res, err := run("--name", GenerateContainerID(), "-d", "-P", "-p", forward, RabbitMQImageName)
return res, err
})
return
}
// ConnectToRabbitMQ starts a RabbitMQ image and passes the amqp url to the connector callback.
// The url will match the ip:port pattern (e.g. 123.123.123.123:4241)
func ConnectToRabbitMQ(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupRabbitMQContainer()
if err != nil {
return c, fmt.Errorf("Could not set up RabbitMQ container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up RabbitMQ container.")
}

View File

@ -1,42 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupRedisContainer sets up a real Redis instance for testing purposes
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupRedisContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 6379)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(RedisImageName, port, 15*time.Second, func() (string, error) {
return run("--name", GenerateContainerID(), "-d", "-P", "-p", forward, RedisImageName)
})
return
}
// ConnectToRedis starts a Redis image and passes the database url to the connector callback function.
// The url will match the ip:port pattern (e.g. 123.123.123.123:6379)
func ConnectToRedis(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupRedisContainer()
if err != nil {
return c, fmt.Errorf("Could not set up Redis container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up Redis container.")
}

View File

@ -1,43 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupRethinkDBContainer sets up a real RethinkDB instance for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupRethinkDBContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 28015)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(RethinkDBImageName, port, 10*time.Second, func() (string, error) {
res, err := run("--name", GenerateContainerID(), "-d", "-P", "-p", forward, RethinkDBImageName)
return res, err
})
return
}
// ConnectToRethinkDB starts a RethinkDB image and passes the database url to the connector callback.
// The url will match the ip:port pattern (e.g. 123.123.123.123:4241)
func ConnectToRethinkDB(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupRethinkDBContainer()
if err != nil {
return c, fmt.Errorf("Could not set up RethinkDB container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not set up RethinkDB container.")
}

View File

@ -1,87 +0,0 @@
package dockertest
import "github.com/ory-am/common/env"
// Dockertest configuration
var (
// Debug if set, prevents any container from being removed.
Debug bool
// DockerMachineAvailable if true, uses docker-machine to run docker commands (for running tests on Windows and Mac OS)
DockerMachineAvailable bool
// DockerMachineName is the machine's name. You might want to use a dedicated machine for running your tests.
// You can set this variable either directly or by defining a DOCKERTEST_IMAGE_NAME env variable.
DockerMachineName = env.Getenv("DOCKERTEST_IMAGE_NAME", "default")
// BindDockerToLocalhost if set, forces docker to bind the image to localhost. This for example is required when running tests on travis-ci.
// You can set this variable either directly or by defining a DOCKERTEST_BIND_LOCALHOST env variable.
// FIXME DOCKER_BIND_LOCALHOST remove legacy support
BindDockerToLocalhost = env.Getenv("DOCKERTEST_BIND_LOCALHOST", env.Getenv("DOCKER_BIND_LOCALHOST", "1"))
// UseDockerMachine if set, forces docker to use the legacy docker-machine on OSX/Windows.
UseDockerMachine = env.Getenv("DOCKERTEST_LEGACY_DOCKER_MACHINE", "")
// ContainerPrefix will be prepended to all containers started by dockertest to make identification of these "test images" hassle-free.
ContainerPrefix = env.Getenv("DOCKERTEST_CONTAINER_PREFIX", "dockertest-")
)
// Image configuration
var (
// MongoDBImageName is the MongoDB image name on dockerhub.
MongoDBImageName = env.Getenv("DOCKERTEST_MONGODB_IMAGE_NAME", "mongo")
// MySQLImageName is the MySQL image name on dockerhub.
MySQLImageName = env.Getenv("DOCKERTEST_MYSQL_IMAGE_NAME", "mysql")
// PostgresImageName is the PostgreSQL image name on dockerhub.
PostgresImageName = env.Getenv("DOCKERTEST_POSTGRES_IMAGE_NAME", "postgres")
// ElasticSearchImageName is the ElasticSearch image name on dockerhub.
ElasticSearchImageName = env.Getenv("DOCKERTEST_ELASTICSEARCH_IMAGE_NAME", "elasticsearch")
// RedisImageName is the Redis image name on dockerhub.
RedisImageName = env.Getenv("DOCKERTEST_REDIS_IMAGE_NAME", "redis")
// NSQImageName is the NSQ image name on dockerhub.
NSQImageName = env.Getenv("DOCKERTEST_NSQ_IMAGE_NAME", "nsqio/nsq")
// RethinkDBImageName is the RethinkDB image name on dockerhub.
RethinkDBImageName = env.Getenv("DOCKERTEST_RETHINKDB_IMAGE_NAME", "rethinkdb")
// RabbitMQImage name is the RabbitMQ image name on dockerhub.
RabbitMQImageName = env.Getenv("DOCKERTEST_RABBITMQ_IMAGE_NAME", "rabbitmq")
// ActiveMQImage name is the ActiveMQ image name on dockerhub.
ActiveMQImageName = env.Getenv("DOCKERTEST_ACTIVEMQ_IMAGE_NAME", "webcenter/activemq")
// MockserverImageName name is the Mockserver image name on dockerhub.
MockserverImageName = env.Getenv("DOCKERTEST_MOCKSERVER_IMAGE_NAME", "jamesdbloom/mockserver")
// ConsulImageName is the Consul image name on dockerhub.
ConsulImageName = env.Getenv("DOCKERTEST_CONSUL_IMAGE_NAME", "consul")
// ZooKeeperImageName is the ZooKeeper image name on dockerhub.
ZooKeeperImageName = env.Getenv("DOCKERTEST_ZOOKEEPER_IMAGE_NAME", "jplock/zookeeper")
// CassandraImageName is the Cassandra image name on dockerhub.
CassandraImageName = env.Getenv("DOCKERTEST_CASSANDRA_IMAGE_NAME", "cassandra")
// EtcdImageName is the etcd image name on dockerhub.
EtcdImageName = env.Getenv("DOCKERTEST_ETCD_IMAGE_NAME", "quay.io/coreos/etcd")
)
// Username and password configuration
var (
// MySQLUsername must be passed as username when connecting to mysql
MySQLUsername = "root"
// MySQLPassword must be passed as password when connecting to mysql
MySQLPassword = "root"
// PostgresUsername must be passed as username when connecting to postgres
PostgresUsername = "postgres"
// PostgresPassword must be passed as password when connecting to postgres
PostgresPassword = "docker"
)

View File

@ -1,43 +0,0 @@
package dockertest
import (
"errors"
"fmt"
"log"
"time"
)
// SetupZooKeeperContainer sets up a real ZooKeeper node for testing purposes,
// using a Docker container. It returns the container ID and its IP address,
// or makes the test fail on error.
func SetupZooKeeperContainer() (c ContainerID, ip string, port int, err error) {
port = RandomPort()
forward := fmt.Sprintf("%d:%d", port, 2181)
if BindDockerToLocalhost != "" {
forward = "127.0.0.1:" + forward
}
c, ip, err = SetupContainer(ZooKeeperImageName, port, 10*time.Second, func() (string, error) {
return run("--name", GenerateContainerID(), "-d", "-p", forward, ZooKeeperImageName)
})
return
}
// ConnectToZooKeeper starts a ZooKeeper image and passes the nodes connection string to the connector callback function.
// The connection string will match the ip:port pattern.
func ConnectToZooKeeper(tries int, delay time.Duration, connector func(url string) bool) (c ContainerID, err error) {
c, ip, port, err := SetupZooKeeperContainer()
if err != nil {
return c, fmt.Errorf("Could not setup ZooKeeper container: %v", err)
}
for try := 0; try <= tries; try++ {
time.Sleep(delay)
url := fmt.Sprintf("%s:%d", ip, port)
if connector(url) {
return c, nil
}
log.Printf("Try %d failed. Retrying.", try)
}
return c, errors.New("Could not setup ZooKeeper container.")
}

8
vendor/modules.txt vendored
View File

@ -214,7 +214,7 @@ github.com/go-errors/errors
github.com/go-ldap/ldap
# github.com/go-sql-driver/mysql v1.4.1
github.com/go-sql-driver/mysql
# github.com/go-test/deep v1.0.1
# github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31
github.com/go-test/deep
# github.com/gocql/gocql v0.0.0-20190402132108-0e1d5de854df
github.com/gocql/gocql
@ -480,8 +480,6 @@ github.com/opencontainers/image-spec/specs-go/v1
github.com/opencontainers/image-spec/specs-go
# github.com/opencontainers/runc v0.1.1
github.com/opencontainers/runc/libcontainer/user
# github.com/ory-am/common v0.4.0
github.com/ory-am/common/env
# github.com/ory/dockertest v3.3.4+incompatible
github.com/ory/dockertest
github.com/ory/dockertest/docker
@ -510,8 +508,6 @@ github.com/ory/dockertest/docker/types/strslice
github.com/ory/dockertest/docker/types/versions
# github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/patrickmn/go-cache
# github.com/pborman/uuid v1.2.0
github.com/pborman/uuid
# github.com/pierrec/lz4 v2.0.5+incompatible
github.com/pierrec/lz4
github.com/pierrec/lz4/internal/xxh32
@ -753,8 +749,6 @@ gopkg.in/mgo.v2/bson
gopkg.in/mgo.v2/internal/sasl
gopkg.in/mgo.v2/internal/scram
gopkg.in/mgo.v2/internal/json
# gopkg.in/ory-am/dockertest.v2 v2.2.3
gopkg.in/ory-am/dockertest.v2
# gopkg.in/ory-am/dockertest.v3 v3.3.4
gopkg.in/ory-am/dockertest.v3
# gopkg.in/square/go-jose.v2 v2.3.1

View File

@ -47,7 +47,7 @@ $ pip install ansible-modules-hashivault
### C&#35;
* [VaultSharp](https://github.com/rajanadar/VaultSharp) (.NET Core >= 1.0.0, .NET 4.5, .NET 4.6, Mono, iOS, Android, Mac, UWP etc.)
* [VaultSharp](https://github.com/rajanadar/VaultSharp) (.NET Standard 2.0 & 1.3, .NET Core >= 1.0.0, .NET 4.5, .NET 4.6, Mono, iOS, Android, Mac, UWP etc.)
```shell
$ Install-Package VaultSharp

View File

@ -230,6 +230,9 @@ updated with the new attributes.
TTL are capped to `max_sts_ttl`). Valid only when `credential_type` is one of
`assumed_role` or `federation_token`.
- `user_path` `(string)` - The path for the user name. Valid only when
`credential_type` is `iam_user`. Default is `/`
Legacy parameters:
These parameters are supported for backwards compatibility only. They cannot be

View File

@ -194,6 +194,10 @@ $ curl \
| :------------------------| :------------------------ |
| `GET` | `/gcp/roleset/:name` |
### Parameters
- `name` (`string:<required>`): Name of the roleset to delete.
### Sample Request
```
@ -234,10 +238,6 @@ $ curl \
| `LIST` | `/gcp/rolesets` |
| Method | Path |
| :------------------------| :------------------------ |
| `LIST` | `/gcp/roleset` |
### Sample Request
```
@ -260,6 +260,27 @@ $ curl \
}
```
## Delete Roleset
This endpoint deletes an existing roleset by the given name.
| Method | Path |
| :------------------------| :------------------------ |
| `DELETE` | `/gcp/roleset/:name` |
### Parameters
- `name` (`string:<required>`): Name of the roleset to delete.
### Sample Request
```
$ curl \
--header "X-Vault-Token: ..." \
--request DELETE \
https://127.0.0.1:8200/v1/gcp/roleset/my-token-roleset
```
## Generate Secret (IAM Service Account Creds): OAuth2 Access Token

View File

@ -545,7 +545,8 @@ $ curl \
This endpoint allows submitting the signed CA certificate corresponding to a
private key generated via `/pki/intermediate/generate`. The certificate should
be submitted in PEM format; see the documentation for `/pki/config/ca` for some
be submitted in PEM format; see the documentation for
[/pki/config/ca](/api/secret/pki/index.html#submit-ca-information) for some
hints on submitting.
| Method | Path |

View File

@ -117,6 +117,8 @@ flags](/docs/commands/index.html) included on all commands.
maximumTTLs. This is specified as a numeric string with suffix like "30s" or
"5m".
- `-type` `(string: "service")` - The type of token to create. Can be "service" or "batch".
- `-use-limit` `(int: 0)` - Number of times this token can be used. After the
last use, the token is automatically revoked. By default, tokens can be used
an unlimited number of times until their expiration.

View File

@ -199,7 +199,7 @@ few different formats:
include the resource nested in the parent project.
```text
# compute alpha zome
# compute alpha zone
https://www.googleapis.com/compute/alpha/projects/my-project/zones/us-central1-c
```