1
+ package com.vauthenticator.server.keys.adapter
2
+
3
+ import com.vauthenticator.server.extentions.encoder
4
+ import com.vauthenticator.server.extentions.valueAsStringFor
5
+ import com.vauthenticator.server.keys.domain.KeyPurpose.MFA
6
+ import com.vauthenticator.server.keys.domain.KeyPurpose.SIGNATURE
7
+ import com.vauthenticator.server.keys.domain.KeyStorage
8
+ import com.vauthenticator.server.keys.domain.KeyType.ASYMMETRIC
9
+ import com.vauthenticator.server.keys.domain.KeyType.SYMMETRIC
10
+ import com.vauthenticator.server.keys.domain.Keys
11
+ import com.vauthenticator.server.keys.domain.Kid
12
+ import com.vauthenticator.server.support.DynamoDbUtils.dynamoMfaKeysTableName
13
+ import com.vauthenticator.server.support.DynamoDbUtils.dynamoSignatureKeysTableName
14
+ import com.vauthenticator.server.support.KeysUtils.aKeyFor
15
+ import com.vauthenticator.server.support.KeysUtils.aKid
16
+ import com.vauthenticator.server.support.KeysUtils.aMasterKey
17
+ import com.vauthenticator.server.support.KeysUtils.aSignatureDataKey
18
+ import com.vauthenticator.server.support.KeysUtils.aSimmetricDataKey
19
+ import com.vauthenticator.server.support.KeysUtils.anotherKid
20
+ import org.junit.jupiter.api.Assertions.assertEquals
21
+ import org.junit.jupiter.api.BeforeEach
22
+ import org.junit.jupiter.api.Test
23
+ import software.amazon.awssdk.services.dynamodb.model.AttributeValue
24
+ import java.time.Duration
25
+ import java.time.Instant
26
+ import kotlin.test.assertNotNull
27
+
28
+ abstract class AbstractKeyStorageTest {
29
+
30
+ private val masterKid = aMasterKey
31
+ private val now = Instant .now()
32
+
33
+ private lateinit var uut: KeyStorage
34
+
35
+ abstract fun initKeyStorage (): KeyStorage
36
+ abstract fun resetDatabase ()
37
+ abstract fun getActual (kid : Kid , tableName : String ): MutableMap <String , AttributeValue >
38
+
39
+
40
+ @BeforeEach
41
+ fun setUp () {
42
+ resetDatabase()
43
+ uut = initKeyStorage()
44
+ }
45
+
46
+ @Test
47
+ fun `when store a new data key pair` () {
48
+ uut.store(masterKid, aKid, aSignatureDataKey, ASYMMETRIC , SIGNATURE )
49
+
50
+ val actual = getActual(aKid, dynamoSignatureKeysTableName)
51
+ assertEquals(aKid.content(), actual.valueAsStringFor(" key_id" ))
52
+ assertEquals(masterKid.content(), actual.valueAsStringFor(" master_key_id" ))
53
+ assertEquals(
54
+ encoder.encode(aSignatureDataKey.encryptedPrivateKey)
55
+ .decodeToString(), actual.valueAsStringFor(" encrypted_private_key" )
56
+ )
57
+ assertEquals(
58
+ encoder.encode(aSignatureDataKey.publicKey.get()).decodeToString(),
59
+ actual.valueAsStringFor(" public_key" )
60
+ )
61
+ }
62
+
63
+ @Test
64
+ fun `when store a new data key for mfa` () {
65
+ uut.store(masterKid, aKid, aSimmetricDataKey, SYMMETRIC , MFA )
66
+
67
+ val actual = getActual(aKid, dynamoMfaKeysTableName)
68
+ assertEquals(aKid.content(), actual.valueAsStringFor(" key_id" ))
69
+ assertEquals(masterKid.content(), actual.valueAsStringFor(" master_key_id" ))
70
+ assertEquals(
71
+ encoder.encode(aSimmetricDataKey.encryptedPrivateKey)
72
+ .decodeToString(), actual.valueAsStringFor(" encrypted_private_key" )
73
+ )
74
+ }
75
+
76
+ @Test
77
+ fun `when find an mfa key` () {
78
+ uut.store(masterKid, aKid, aSimmetricDataKey, SYMMETRIC , MFA )
79
+ val actual = uut.findOne(aKid, MFA )
80
+ val excpected = aKeyFor(masterKid.content(), aKid.content(), SYMMETRIC , MFA )
81
+ assertEquals(excpected, actual)
82
+ }
83
+
84
+ @Test
85
+ fun `when find an signature key` () {
86
+ uut.store(masterKid, aKid, aSignatureDataKey, ASYMMETRIC , SIGNATURE )
87
+ val actual = uut.findOne(aKid, SIGNATURE )
88
+ val excpected = aKeyFor(masterKid.content(), aKid.content(), ASYMMETRIC , SIGNATURE )
89
+ assertEquals(excpected, actual)
90
+ }
91
+
92
+ @Test
93
+ fun `when find all signature keys` () {
94
+ uut.store(masterKid, aKid, aSignatureDataKey, ASYMMETRIC , SIGNATURE )
95
+ uut.store(masterKid, anotherKid, aSignatureDataKey, ASYMMETRIC , SIGNATURE )
96
+ val actual = uut.signatureKeys()
97
+ val excpected = Keys (
98
+ listOf (
99
+ aKeyFor(masterKid.content(), aKid.content(), ASYMMETRIC , SIGNATURE ),
100
+ aKeyFor(masterKid.content(), anotherKid.content(), ASYMMETRIC , SIGNATURE )
101
+ )
102
+ )
103
+ assertEquals(excpected, actual)
104
+ }
105
+
106
+ @Test
107
+ fun `when a signature key is deleted` () {
108
+ uut.store(masterKid, aKid, aSignatureDataKey, ASYMMETRIC , SIGNATURE )
109
+ val storedKey = uut.findOne(aKid, SIGNATURE )
110
+ assertNotNull(storedKey)
111
+
112
+ uut.justDeleteKey(aKid, SIGNATURE )
113
+ val actual = getActual(aKid, dynamoSignatureKeysTableName)
114
+ assertEquals(emptyMap<String , AttributeValue >(), actual)
115
+ }
116
+
117
+ @Test
118
+ fun `when a signature key planned to be deleted` () {
119
+ uut.store(masterKid, aKid, aSignatureDataKey, ASYMMETRIC , SIGNATURE )
120
+ val storedKey = uut.findOne(aKid, SIGNATURE )
121
+ assertNotNull(storedKey)
122
+
123
+ val ttl = Duration .ofSeconds(1 )
124
+ uut.keyDeleteJodPlannedFor(aKid, ttl, SIGNATURE )
125
+
126
+ val actual = getActual(aKid, dynamoSignatureKeysTableName)
127
+ val expectedTTl = now.epochSecond + 1
128
+ assertEquals(false , (actual[" enabled" ] as AttributeValue ).bool())
129
+ assertEquals(expectedTTl, (actual[" key_expiration_date_timestamp" ] as AttributeValue ).n().toLong())
130
+ }
131
+
132
+ @Test
133
+ fun `when a signature key deletion planning is ignored` () {
134
+ uut.store(masterKid, aKid, aSignatureDataKey, ASYMMETRIC , SIGNATURE )
135
+ val storedKey = uut.findOne(aKid, SIGNATURE )
136
+ assertNotNull(storedKey)
137
+
138
+ uut.keyDeleteJodPlannedFor(aKid, Duration .ofSeconds(1 ), SIGNATURE )
139
+
140
+ val actual = getActual(aKid, dynamoSignatureKeysTableName)
141
+ val expectedTTl = now.epochSecond + 1
142
+ assertEquals(false , (actual[" enabled" ] as AttributeValue ).bool())
143
+ assertEquals(expectedTTl, (actual[" key_expiration_date_timestamp" ] as AttributeValue ).n().toLong())
144
+
145
+ uut.keyDeleteJodPlannedFor(aKid, Duration .ofSeconds(10 ), SIGNATURE )
146
+
147
+ val actualAfterReplanning = getActual(aKid, dynamoSignatureKeysTableName)
148
+ val expectedTTlAfterReplanning = now.epochSecond + 1
149
+ assertEquals(false , (actualAfterReplanning[" enabled" ] as AttributeValue ).bool())
150
+ assertEquals(expectedTTlAfterReplanning, (actualAfterReplanning[" key_expiration_date_timestamp" ] as AttributeValue ).n().toLong())
151
+ }
152
+
153
+ }
0 commit comments