Apply make fmt

This commit is contained in:
Abel Luck 2025-06-03 13:24:01 +02:00
parent d8eda81e0e
commit 3702fc3acb
11 changed files with 96 additions and 100 deletions

View file

@ -64,7 +64,6 @@ func (p *ScaffoldingProvider) Resources(ctx context.Context) []func() resource.R
} }
} }
func (p *ScaffoldingProvider) DataSources(ctx context.Context) []func() datasource.DataSource { func (p *ScaffoldingProvider) DataSources(ctx context.Context) []func() datasource.DataSource {
return []func() datasource.DataSource{ return []func() datasource.DataSource{
NewTorObfs4BridgeLineDataSource, NewTorObfs4BridgeLineDataSource,
@ -72,8 +71,7 @@ func (p *ScaffoldingProvider) DataSources(ctx context.Context) []func() datasour
} }
func (p *ScaffoldingProvider) Functions(ctx context.Context) []func() function.Function { func (p *ScaffoldingProvider) Functions(ctx context.Context) []func() function.Function {
return []func() function.Function{ return []func() function.Function{}
}
} }
func New(version string) func() provider.Provider { func New(version string) func() provider.Provider {
@ -82,4 +80,4 @@ func New(version string) func() provider.Provider {
version: version, version: version,
} }
} }
} }

View file

@ -22,4 +22,4 @@ func testAccPreCheck(t *testing.T) {
// You can add code here to run prior to any test case execution, for example assertions // You can add code here to run prior to any test case execution, for example assertions
// about the appropriate environment variables being set are common to see in a pre-check // about the appropriate environment variables being set are common to see in a pre-check
// function. // function.
} }

View file

@ -104,4 +104,4 @@ func (d *TorObfs4BridgeLineDataSource) Read(ctx context.Context, req datasource.
// Save data into Terraform state // Save data into Terraform state
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
} }

View file

@ -23,23 +23,23 @@ func TestTorObfs4BridgeLineDataSource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc( Check: resource.ComposeAggregateTestCheckFunc(
// Check that the data source was created // Check that the data source was created
resource.TestCheckResourceAttrSet("data.tor_obfs4_bridge_line.test", "id"), resource.TestCheckResourceAttrSet("data.tor_obfs4_bridge_line.test", "id"),
// Check input values are preserved // Check input values are preserved
resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test", "ip_address", "192.0.2.1"), resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test", "ip_address", "192.0.2.1"),
resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test", "port", "443"), resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test", "port", "443"),
// Check computed values are generated // Check computed values are generated
resource.TestCheckResourceAttrSet("data.tor_obfs4_bridge_line.test", "bridge_line"), resource.TestCheckResourceAttrSet("data.tor_obfs4_bridge_line.test", "bridge_line"),
// Check bridge line format // Check bridge line format
resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test", "bridge_line", resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test", "bridge_line",
regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:443 [0-9a-f]{40} cert=[A-Za-z0-9+/]+ iat-mode=[0-2]$`)), regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:443 [0-9a-f]{40} cert=[A-Za-z0-9+/]+ iat-mode=[0-2]$`)),
// Check that input values are used correctly // Check that input values are used correctly
resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test", "identity_fingerprint_sha1", "tor_relay_identity_rsa.test", "public_key_fingerprint_sha1"), resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test", "identity_fingerprint_sha1", "tor_relay_identity_rsa.test", "public_key_fingerprint_sha1"),
resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test", "obfs4_state_certificate", "tor_obfs4_state.test", "certificate"), resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test", "obfs4_state_certificate", "tor_obfs4_state.test", "certificate"),
resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test", "obfs4_state_iat_mode", "tor_obfs4_state.test", "iat_mode"), resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test", "obfs4_state_iat_mode", "tor_obfs4_state.test", "iat_mode"),
// Validate bridge line consistency // Validate bridge line consistency
testTorObfs4BridgeLineConsistency("data.tor_obfs4_bridge_line.test"), testTorObfs4BridgeLineConsistency("data.tor_obfs4_bridge_line.test"),
), ),
@ -57,7 +57,7 @@ func TestTorObfs4BridgeLineDataSourceWithCustomIATMode(t *testing.T) {
Config: testTorObfs4BridgeLineDataSourceConfigWithIATMode(2), Config: testTorObfs4BridgeLineDataSourceConfigWithIATMode(2),
Check: resource.ComposeAggregateTestCheckFunc( Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test", "obfs4_state_iat_mode", "2"), resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test", "obfs4_state_iat_mode", "2"),
resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test", "bridge_line", resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test", "bridge_line",
regexp.MustCompile(`iat-mode=2$`)), regexp.MustCompile(`iat-mode=2$`)),
testTorObfs4BridgeLineConsistency("data.tor_obfs4_bridge_line.test"), testTorObfs4BridgeLineConsistency("data.tor_obfs4_bridge_line.test"),
), ),
@ -77,15 +77,15 @@ func TestTorObfs4BridgeLineDataSourceMultiplePorts(t *testing.T) {
// Check first bridge line // Check first bridge line
resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test1", "ip_address", "192.0.2.1"), resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test1", "ip_address", "192.0.2.1"),
resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test1", "port", "443"), resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test1", "port", "443"),
resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test1", "bridge_line", resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test1", "bridge_line",
regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:443`)), regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:443`)),
// Check second bridge line (same obfs4_state, different port) // Check second bridge line (same obfs4_state, different port)
resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test2", "ip_address", "192.0.2.1"), resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test2", "ip_address", "192.0.2.1"),
resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test2", "port", "80"), resource.TestCheckResourceAttr("data.tor_obfs4_bridge_line.test2", "port", "80"),
resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test2", "bridge_line", resource.TestMatchResourceAttr("data.tor_obfs4_bridge_line.test2", "bridge_line",
regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:80`)), regexp.MustCompile(`^Bridge obfs4 192\.0\.2\.1:80`)),
// Verify both use the same certificate and fingerprint (same obfs4_state) // Verify both use the same certificate and fingerprint (same obfs4_state)
resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test1", "obfs4_state_certificate", "data.tor_obfs4_bridge_line.test2", "obfs4_state_certificate"), resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test1", "obfs4_state_certificate", "data.tor_obfs4_bridge_line.test2", "obfs4_state_certificate"),
resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test1", "identity_fingerprint_sha1", "data.tor_obfs4_bridge_line.test2", "identity_fingerprint_sha1"), resource.TestCheckResourceAttrPair("data.tor_obfs4_bridge_line.test1", "identity_fingerprint_sha1", "data.tor_obfs4_bridge_line.test2", "identity_fingerprint_sha1"),
@ -175,23 +175,23 @@ func testTorObfs4BridgeLineConsistency(resourceName string) resource.TestCheckFu
if !ok { if !ok {
return fmt.Errorf("Resource not found: %s", resourceName) return fmt.Errorf("Resource not found: %s", resourceName)
} }
ipAddress := rs.Primary.Attributes["ip_address"] ipAddress := rs.Primary.Attributes["ip_address"]
port := rs.Primary.Attributes["port"] port := rs.Primary.Attributes["port"]
fingerprint := rs.Primary.Attributes["identity_fingerprint_sha1"] fingerprint := rs.Primary.Attributes["identity_fingerprint_sha1"]
certificate := rs.Primary.Attributes["obfs4_state_certificate"] certificate := rs.Primary.Attributes["obfs4_state_certificate"]
iatMode := rs.Primary.Attributes["obfs4_state_iat_mode"] iatMode := rs.Primary.Attributes["obfs4_state_iat_mode"]
bridgeLine := rs.Primary.Attributes["bridge_line"] bridgeLine := rs.Primary.Attributes["bridge_line"]
// Verify bridge line format matches expected pattern // Verify bridge line format matches expected pattern
expectedBridgeLine := fmt.Sprintf("Bridge obfs4 %s:%s %s cert=%s iat-mode=%s", expectedBridgeLine := fmt.Sprintf("Bridge obfs4 %s:%s %s cert=%s iat-mode=%s",
ipAddress, port, fingerprint, certificate, iatMode) ipAddress, port, fingerprint, certificate, iatMode)
if bridgeLine != expectedBridgeLine { if bridgeLine != expectedBridgeLine {
return fmt.Errorf("Bridge line doesn't match expected format.\nExpected: %s\nActual: %s", return fmt.Errorf("Bridge line doesn't match expected format.\nExpected: %s\nActual: %s",
expectedBridgeLine, bridgeLine) expectedBridgeLine, bridgeLine)
} }
return nil return nil
} }
} }

View file

@ -39,17 +39,17 @@ type TorObfs4StateResource struct{}
// TorObfs4StateResourceModel describes the resource data model. // TorObfs4StateResourceModel describes the resource data model.
type TorObfs4StateResourceModel struct { type TorObfs4StateResourceModel struct {
Id types.String `tfsdk:"id"` Id types.String `tfsdk:"id"`
RsaIdentityPrivateKey types.String `tfsdk:"rsa_identity_private_key"` RsaIdentityPrivateKey types.String `tfsdk:"rsa_identity_private_key"`
Ed25519IdentityPrivateKey types.String `tfsdk:"ed25519_identity_private_key"` Ed25519IdentityPrivateKey types.String `tfsdk:"ed25519_identity_private_key"`
NodeId types.String `tfsdk:"node_id"` NodeId types.String `tfsdk:"node_id"`
PrivateKey types.String `tfsdk:"private_key"` PrivateKey types.String `tfsdk:"private_key"`
PublicKey types.String `tfsdk:"public_key"` PublicKey types.String `tfsdk:"public_key"`
DrbgSeed types.String `tfsdk:"drbg_seed"` DrbgSeed types.String `tfsdk:"drbg_seed"`
IatMode types.Int64 `tfsdk:"iat_mode"` IatMode types.Int64 `tfsdk:"iat_mode"`
Certificate types.String `tfsdk:"certificate"` Certificate types.String `tfsdk:"certificate"`
StateJson types.String `tfsdk:"state_json"` StateJson types.String `tfsdk:"state_json"`
BridgeLine types.String `tfsdk:"bridge_line"` BridgeLine types.String `tfsdk:"bridge_line"`
} }
// obfs4StateJson represents the JSON structure for the state file // obfs4StateJson represents the JSON structure for the state file
@ -164,7 +164,7 @@ func (r *TorObfs4StateResource) Create(ctx context.Context, req resource.CreateR
// Generate obfs4 state // Generate obfs4 state
err := r.generateObfs4State(ctx, &data) err := r.generateObfs4State(ctx, &data)
if err != nil { if err != nil {
resp.Diagnostics.AddError("obfs4 State Generation Error", resp.Diagnostics.AddError("obfs4 State Generation Error",
fmt.Sprintf("Unable to generate obfs4 state: %s", err)) fmt.Sprintf("Unable to generate obfs4 state: %s", err))
return return
} }
@ -260,7 +260,6 @@ func (r *TorObfs4StateResource) Delete(ctx context.Context, req resource.DeleteR
tflog.Trace(ctx, "deleted obfs4 state resource") tflog.Trace(ctx, "deleted obfs4 state resource")
} }
// generateObfs4State generates all the obfs4 state fields // generateObfs4State generates all the obfs4 state fields
func (r *TorObfs4StateResource) generateObfs4State(ctx context.Context, data *TorObfs4StateResourceModel) error { func (r *TorObfs4StateResource) generateObfs4State(ctx context.Context, data *TorObfs4StateResourceModel) error {
// Derive node ID from RSA identity key (required) // Derive node ID from RSA identity key (required)
@ -318,7 +317,7 @@ func (r *TorObfs4StateResource) generateCertificate(nodeIdHex, publicKeyHex stri
if err != nil { if err != nil {
return "", fmt.Errorf("failed to decode node ID: %w", err) return "", fmt.Errorf("failed to decode node ID: %w", err)
} }
publicKeyBytes, err := hex.DecodeString(publicKeyHex) publicKeyBytes, err := hex.DecodeString(publicKeyHex)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to decode public key: %w", err) return "", fmt.Errorf("failed to decode public key: %w", err)
@ -340,7 +339,7 @@ func (r *TorObfs4StateResource) generateCertificate(nodeIdHex, publicKeyHex stri
// Base64 encode and remove padding // Base64 encode and remove padding
cert := base64.StdEncoding.EncodeToString(certBytes) cert := base64.StdEncoding.EncodeToString(certBytes)
cert = strings.TrimSuffix(cert, "==") cert = strings.TrimSuffix(cert, "==")
return cert, nil return cert, nil
} }
@ -367,8 +366,8 @@ func (r *TorObfs4StateResource) generateBridgeLine(certificate string, iatMode i
// Use placeholder values that users can easily replace // Use placeholder values that users can easily replace
placeholderIP := "<IP:PORT>" placeholderIP := "<IP:PORT>"
placeholderFingerprint := "<FINGERPRINT>" placeholderFingerprint := "<FINGERPRINT>"
return fmt.Sprintf("Bridge obfs4 %s %s cert=%s iat-mode=%d", return fmt.Sprintf("Bridge obfs4 %s %s cert=%s iat-mode=%d",
placeholderIP, placeholderFingerprint, certificate, iatMode) placeholderIP, placeholderFingerprint, certificate, iatMode)
} }
@ -414,7 +413,7 @@ func (r *TorObfs4StateResource) deriveNodeIdFromRsaKey(rsaPrivateKeyPem string)
// Generate SHA1 hash of public key (this is the relay fingerprint/node ID) // Generate SHA1 hash of public key (this is the relay fingerprint/node ID)
hash := sha1.Sum(publicKeyBytes) hash := sha1.Sum(publicKeyBytes)
// Create node ID from the first 20 bytes (which is all of SHA1) // Create node ID from the first 20 bytes (which is all of SHA1)
nodeId, err := ntor.NewNodeID(hash[:]) nodeId, err := ntor.NewNodeID(hash[:])
if err != nil { if err != nil {
@ -422,4 +421,4 @@ func (r *TorObfs4StateResource) deriveNodeIdFromRsaKey(rsaPrivateKeyPem string)
} }
return nodeId, nil return nodeId, nil
} }

View file

@ -27,7 +27,7 @@ func TestTorObfs4StateResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc( Check: resource.ComposeAggregateTestCheckFunc(
// Check that the resource was created // Check that the resource was created
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "id"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "id"),
// Check that all fields are generated // Check that all fields are generated
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "node_id"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "node_id"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "private_key"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "private_key"),
@ -36,31 +36,31 @@ func TestTorObfs4StateResource(t *testing.T) {
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "certificate"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "certificate"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "state_json"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "state_json"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "bridge_line"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "bridge_line"),
// Check default iat_mode // Check default iat_mode
resource.TestCheckResourceAttr("tor_obfs4_state.test", "iat_mode", "0"), resource.TestCheckResourceAttr("tor_obfs4_state.test", "iat_mode", "0"),
// Check field lengths (hex-encoded) // Check field lengths (hex-encoded)
resource.TestMatchResourceAttr("tor_obfs4_state.test", "node_id", regexp.MustCompile(`^[0-9a-f]{40}$`)), resource.TestMatchResourceAttr("tor_obfs4_state.test", "node_id", regexp.MustCompile(`^[0-9a-f]{40}$`)),
resource.TestMatchResourceAttr("tor_obfs4_state.test", "private_key", regexp.MustCompile(`^[0-9a-f]{64}$`)), resource.TestMatchResourceAttr("tor_obfs4_state.test", "private_key", regexp.MustCompile(`^[0-9a-f]{64}$`)),
resource.TestMatchResourceAttr("tor_obfs4_state.test", "public_key", regexp.MustCompile(`^[0-9a-f]{64}$`)), resource.TestMatchResourceAttr("tor_obfs4_state.test", "public_key", regexp.MustCompile(`^[0-9a-f]{64}$`)),
resource.TestMatchResourceAttr("tor_obfs4_state.test", "drbg_seed", regexp.MustCompile(`^[0-9a-f]{48}$`)), resource.TestMatchResourceAttr("tor_obfs4_state.test", "drbg_seed", regexp.MustCompile(`^[0-9a-f]{48}$`)),
// Check certificate format (base64 without padding) // Check certificate format (base64 without padding)
resource.TestMatchResourceAttr("tor_obfs4_state.test", "certificate", regexp.MustCompile(`^[A-Za-z0-9+/]+$`)), resource.TestMatchResourceAttr("tor_obfs4_state.test", "certificate", regexp.MustCompile(`^[A-Za-z0-9+/]+$`)),
// Check bridge_line format // Check bridge_line format
resource.TestMatchResourceAttr("tor_obfs4_state.test", "bridge_line", regexp.MustCompile(`^Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=[A-Za-z0-9+/]+ iat-mode=0$`)), resource.TestMatchResourceAttr("tor_obfs4_state.test", "bridge_line", regexp.MustCompile(`^Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=[A-Za-z0-9+/]+ iat-mode=0$`)),
// Check that the JSON is valid // Check that the JSON is valid
testTorObfs4StateValidateJSON("tor_obfs4_state.test"), testTorObfs4StateValidateJSON("tor_obfs4_state.test"),
// Check that certificate is properly generated from node_id + public_key // Check that certificate is properly generated from node_id + public_key
testTorObfs4StateCertificateValidity("tor_obfs4_state.test"), testTorObfs4StateCertificateValidity("tor_obfs4_state.test"),
// Check that bridge_line contains the correct certificate and iat_mode // Check that bridge_line contains the correct certificate and iat_mode
testTorObfs4StateBridgeLineValidity("tor_obfs4_state.test"), testTorObfs4StateBridgeLineValidity("tor_obfs4_state.test"),
// Verify the external identity keys are being used // Verify the external identity keys are being used
resource.TestCheckResourceAttrPair("tor_obfs4_state.test", "rsa_identity_private_key", "tor_relay_identity_rsa.test", "private_key_pem"), resource.TestCheckResourceAttrPair("tor_obfs4_state.test", "rsa_identity_private_key", "tor_relay_identity_rsa.test", "private_key_pem"),
resource.TestCheckResourceAttrPair("tor_obfs4_state.test", "ed25519_identity_private_key", "tor_relay_identity_ed25519.test", "private_key_pem"), resource.TestCheckResourceAttrPair("tor_obfs4_state.test", "ed25519_identity_private_key", "tor_relay_identity_ed25519.test", "private_key_pem"),
@ -72,20 +72,20 @@ func TestTorObfs4StateResource(t *testing.T) {
Check: resource.ComposeAggregateTestCheckFunc( Check: resource.ComposeAggregateTestCheckFunc(
// Check that iat_mode was updated // Check that iat_mode was updated
resource.TestCheckResourceAttr("tor_obfs4_state.test", "iat_mode", "1"), resource.TestCheckResourceAttr("tor_obfs4_state.test", "iat_mode", "1"),
// Check that crypto fields remain unchanged (immutable) // Check that crypto fields remain unchanged (immutable)
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "node_id"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "node_id"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "private_key"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "private_key"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "public_key"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "public_key"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "drbg_seed"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "drbg_seed"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "certificate"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test", "certificate"),
// Check that bridge_line reflects the updated iat_mode // Check that bridge_line reflects the updated iat_mode
resource.TestMatchResourceAttr("tor_obfs4_state.test", "bridge_line", regexp.MustCompile(`^Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=[A-Za-z0-9+/]+ iat-mode=1$`)), resource.TestMatchResourceAttr("tor_obfs4_state.test", "bridge_line", regexp.MustCompile(`^Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=[A-Za-z0-9+/]+ iat-mode=1$`)),
// Check that state_json reflects the updated iat_mode // Check that state_json reflects the updated iat_mode
testTorObfs4StateValidateJSON("tor_obfs4_state.test"), testTorObfs4StateValidateJSON("tor_obfs4_state.test"),
// Check that bridge_line contains the correct certificate and iat_mode // Check that bridge_line contains the correct certificate and iat_mode
testTorObfs4StateBridgeLineValidity("tor_obfs4_state.test"), testTorObfs4StateBridgeLineValidity("tor_obfs4_state.test"),
), ),
@ -125,12 +125,12 @@ func TestTorObfs4StateResourceMultiple(t *testing.T) {
resource.TestCheckResourceAttrSet("tor_obfs4_state.test1", "node_id"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test1", "node_id"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test1", "certificate"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test1", "certificate"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test1", "bridge_line"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test1", "bridge_line"),
// Check second resource // Check second resource
resource.TestCheckResourceAttrSet("tor_obfs4_state.test2", "node_id"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test2", "node_id"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test2", "certificate"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test2", "certificate"),
resource.TestCheckResourceAttrSet("tor_obfs4_state.test2", "bridge_line"), resource.TestCheckResourceAttrSet("tor_obfs4_state.test2", "bridge_line"),
// Verify they have different keys (uniqueness) // Verify they have different keys (uniqueness)
testTorObfs4StateResourcesAreDifferent("tor_obfs4_state.test1", "tor_obfs4_state.test2"), testTorObfs4StateResourcesAreDifferent("tor_obfs4_state.test1", "tor_obfs4_state.test2"),
), ),
@ -142,41 +142,41 @@ func TestTorObfs4StateResourceMultiple(t *testing.T) {
// Unit tests for helper functions // Unit tests for helper functions
func TestTorObfs4StateGenerateCertificate(t *testing.T) { func TestTorObfs4StateGenerateCertificate(t *testing.T) {
resource := &TorObfs4StateResource{} resource := &TorObfs4StateResource{}
// Test with known values // Test with known values
nodeIdHex := "9be04232642c50ee2864c2724500870f5fce6d2d" nodeIdHex := "9be04232642c50ee2864c2724500870f5fce6d2d"
publicKeyHex := "45c9411955294f9b4306e4a65941ea546dee63e1c8a83dd984d1095c4a2f3911" publicKeyHex := "45c9411955294f9b4306e4a65941ea546dee63e1c8a83dd984d1095c4a2f3911"
cert, err := resource.generateCertificate(nodeIdHex, publicKeyHex) cert, err := resource.generateCertificate(nodeIdHex, publicKeyHex)
if err != nil { if err != nil {
t.Fatalf("generateCertificate failed: %v", err) t.Fatalf("generateCertificate failed: %v", err)
} }
// Certificate should be base64 encoded 52 bytes (node_id + public_key) // Certificate should be base64 encoded 52 bytes (node_id + public_key)
if len(cert) != 70 { // 52 bytes base64 encoded without padding = 70 chars if len(cert) != 70 { // 52 bytes base64 encoded without padding = 70 chars
t.Errorf("Expected certificate length 70, got %d", len(cert)) t.Errorf("Expected certificate length 70, got %d", len(cert))
} }
// Verify the certificate decodes correctly // Verify the certificate decodes correctly
decoded, err := base64.StdEncoding.DecodeString(cert + "==") // Add padding for decode decoded, err := base64.StdEncoding.DecodeString(cert + "==") // Add padding for decode
if err != nil { if err != nil {
t.Fatalf("Certificate is not valid base64: %v", err) t.Fatalf("Certificate is not valid base64: %v", err)
} }
if len(decoded) != 52 { if len(decoded) != 52 {
t.Errorf("Expected decoded certificate length 52, got %d", len(decoded)) t.Errorf("Expected decoded certificate length 52, got %d", len(decoded))
} }
// Verify node_id and public_key are correctly concatenated // Verify node_id and public_key are correctly concatenated
nodeIdBytes, _ := hex.DecodeString(nodeIdHex) nodeIdBytes, _ := hex.DecodeString(nodeIdHex)
publicKeyBytes, _ := hex.DecodeString(publicKeyHex) publicKeyBytes, _ := hex.DecodeString(publicKeyHex)
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
if decoded[i] != nodeIdBytes[i] { if decoded[i] != nodeIdBytes[i] {
t.Errorf("Node ID mismatch at byte %d", i) t.Errorf("Node ID mismatch at byte %d", i)
} }
} }
for i := 0; i < 32; i++ { for i := 0; i < 32; i++ {
if decoded[20+i] != publicKeyBytes[i] { if decoded[20+i] != publicKeyBytes[i] {
t.Errorf("Public key mismatch at byte %d", i) t.Errorf("Public key mismatch at byte %d", i)
@ -186,19 +186,19 @@ func TestTorObfs4StateGenerateCertificate(t *testing.T) {
func TestTorObfs4StateGenerateCertificateInvalidInput(t *testing.T) { func TestTorObfs4StateGenerateCertificateInvalidInput(t *testing.T) {
resource := &TorObfs4StateResource{} resource := &TorObfs4StateResource{}
// Test with invalid node ID length // Test with invalid node ID length
_, err := resource.generateCertificate("invalid", "45c9411955294f9b4306e4a65941ea546dee63e1c8a83dd984d1095c4a2f3911") _, err := resource.generateCertificate("invalid", "45c9411955294f9b4306e4a65941ea546dee63e1c8a83dd984d1095c4a2f3911")
if err == nil { if err == nil {
t.Error("Expected error for invalid node ID length") t.Error("Expected error for invalid node ID length")
} }
// Test with invalid public key length // Test with invalid public key length
_, err = resource.generateCertificate("9be04232642c50ee2864c2724500870f5fce6d2d", "invalid") _, err = resource.generateCertificate("9be04232642c50ee2864c2724500870f5fce6d2d", "invalid")
if err == nil { if err == nil {
t.Error("Expected error for invalid public key length") t.Error("Expected error for invalid public key length")
} }
// Test with non-hex input // Test with non-hex input
_, err = resource.generateCertificate("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", "45c9411955294f9b4306e4a65941ea546dee63e1c8a83dd984d1095c4a2f3911") _, err = resource.generateCertificate("zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz", "45c9411955294f9b4306e4a65941ea546dee63e1c8a83dd984d1095c4a2f3911")
if err == nil { if err == nil {
@ -208,24 +208,24 @@ func TestTorObfs4StateGenerateCertificateInvalidInput(t *testing.T) {
func TestTorObfs4StateGenerateBridgeLine(t *testing.T) { func TestTorObfs4StateGenerateBridgeLine(t *testing.T) {
resource := &TorObfs4StateResource{} resource := &TorObfs4StateResource{}
// Test with known values // Test with known values
certificate := "Y+m2Eny/3H4JeW2RwRYGlNXpdYk8MXRbRFuv5AaTZfxnAUbhEnWCTmJM+VTMssTCYrxyag" certificate := "Y+m2Eny/3H4JeW2RwRYGlNXpdYk8MXRbRFuv5AaTZfxnAUbhEnWCTmJM+VTMssTCYrxyag"
iatMode := int64(0) iatMode := int64(0)
bridgeLine := resource.generateBridgeLine(certificate, iatMode) bridgeLine := resource.generateBridgeLine(certificate, iatMode)
expectedBridgeLine := "Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=Y+m2Eny/3H4JeW2RwRYGlNXpdYk8MXRbRFuv5AaTZfxnAUbhEnWCTmJM+VTMssTCYrxyag iat-mode=0" expectedBridgeLine := "Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=Y+m2Eny/3H4JeW2RwRYGlNXpdYk8MXRbRFuv5AaTZfxnAUbhEnWCTmJM+VTMssTCYrxyag iat-mode=0"
if bridgeLine != expectedBridgeLine { if bridgeLine != expectedBridgeLine {
t.Errorf("Expected bridge line:\n%s\nGot:\n%s", expectedBridgeLine, bridgeLine) t.Errorf("Expected bridge line:\n%s\nGot:\n%s", expectedBridgeLine, bridgeLine)
} }
// Test with different iat_mode // Test with different iat_mode
iatMode = int64(2) iatMode = int64(2)
bridgeLine = resource.generateBridgeLine(certificate, iatMode) bridgeLine = resource.generateBridgeLine(certificate, iatMode)
expectedBridgeLine = "Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=Y+m2Eny/3H4JeW2RwRYGlNXpdYk8MXRbRFuv5AaTZfxnAUbhEnWCTmJM+VTMssTCYrxyag iat-mode=2" expectedBridgeLine = "Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=Y+m2Eny/3H4JeW2RwRYGlNXpdYk8MXRbRFuv5AaTZfxnAUbhEnWCTmJM+VTMssTCYrxyag iat-mode=2"
if bridgeLine != expectedBridgeLine { if bridgeLine != expectedBridgeLine {
t.Errorf("Expected bridge line with iat-mode=2:\n%s\nGot:\n%s", expectedBridgeLine, bridgeLine) t.Errorf("Expected bridge line with iat-mode=2:\n%s\nGot:\n%s", expectedBridgeLine, bridgeLine)
} }
@ -233,7 +233,7 @@ func TestTorObfs4StateGenerateBridgeLine(t *testing.T) {
func TestTorObfs4StateGenerateStateJson(t *testing.T) { func TestTorObfs4StateGenerateStateJson(t *testing.T) {
resource := &TorObfs4StateResource{} resource := &TorObfs4StateResource{}
// Create test data // Create test data
data := &TorObfs4StateResourceModel{ data := &TorObfs4StateResourceModel{
NodeId: typeStringValue("9be04232642c50ee2864c2724500870f5fce6d2d"), NodeId: typeStringValue("9be04232642c50ee2864c2724500870f5fce6d2d"),
@ -242,19 +242,19 @@ func TestTorObfs4StateGenerateStateJson(t *testing.T) {
DrbgSeed: typeStringValue("fae8faa79b74d08933251727aab6ca9627736a2387231b03"), DrbgSeed: typeStringValue("fae8faa79b74d08933251727aab6ca9627736a2387231b03"),
IatMode: typeInt64Value(0), IatMode: typeInt64Value(0),
} }
jsonStr, err := resource.generateStateJson(data) jsonStr, err := resource.generateStateJson(data)
if err != nil { if err != nil {
t.Fatalf("generateStateJson failed: %v", err) t.Fatalf("generateStateJson failed: %v", err)
} }
// Parse the JSON to verify structure // Parse the JSON to verify structure
var parsed obfs4StateJson var parsed obfs4StateJson
err = json.Unmarshal([]byte(jsonStr), &parsed) err = json.Unmarshal([]byte(jsonStr), &parsed)
if err != nil { if err != nil {
t.Fatalf("Generated JSON is invalid: %v", err) t.Fatalf("Generated JSON is invalid: %v", err)
} }
// Verify fields // Verify fields
if parsed.NodeId != "9be04232642c50ee2864c2724500870f5fce6d2d" { if parsed.NodeId != "9be04232642c50ee2864c2724500870f5fce6d2d" {
t.Errorf("Node ID mismatch in JSON") t.Errorf("Node ID mismatch in JSON")
@ -332,19 +332,19 @@ func testTorObfs4StateValidateJSON(resourceName string) resource.TestCheckFunc {
if !ok { if !ok {
return fmt.Errorf("Resource not found: %s", resourceName) return fmt.Errorf("Resource not found: %s", resourceName)
} }
stateJsonStr := rs.Primary.Attributes["state_json"] stateJsonStr := rs.Primary.Attributes["state_json"]
if stateJsonStr == "" { if stateJsonStr == "" {
return fmt.Errorf("state_json is empty") return fmt.Errorf("state_json is empty")
} }
// Parse JSON to verify it's valid // Parse JSON to verify it's valid
var parsed obfs4StateJson var parsed obfs4StateJson
err := json.Unmarshal([]byte(stateJsonStr), &parsed) err := json.Unmarshal([]byte(stateJsonStr), &parsed)
if err != nil { if err != nil {
return fmt.Errorf("state_json is not valid JSON: %v", err) return fmt.Errorf("state_json is not valid JSON: %v", err)
} }
// Verify fields match attributes // Verify fields match attributes
if parsed.NodeId != rs.Primary.Attributes["node_id"] { if parsed.NodeId != rs.Primary.Attributes["node_id"] {
return fmt.Errorf("JSON node_id doesn't match attribute") return fmt.Errorf("JSON node_id doesn't match attribute")
@ -358,7 +358,7 @@ func testTorObfs4StateValidateJSON(resourceName string) resource.TestCheckFunc {
if parsed.DrbgSeed != rs.Primary.Attributes["drbg_seed"] { if parsed.DrbgSeed != rs.Primary.Attributes["drbg_seed"] {
return fmt.Errorf("JSON drbg_seed doesn't match attribute") return fmt.Errorf("JSON drbg_seed doesn't match attribute")
} }
return nil return nil
} }
} }
@ -369,22 +369,22 @@ func testTorObfs4StateCertificateValidity(resourceName string) resource.TestChec
if !ok { if !ok {
return fmt.Errorf("Resource not found: %s", resourceName) return fmt.Errorf("Resource not found: %s", resourceName)
} }
nodeIdHex := rs.Primary.Attributes["node_id"] nodeIdHex := rs.Primary.Attributes["node_id"]
publicKeyHex := rs.Primary.Attributes["public_key"] publicKeyHex := rs.Primary.Attributes["public_key"]
certificate := rs.Primary.Attributes["certificate"] certificate := rs.Primary.Attributes["certificate"]
// Regenerate certificate and compare // Regenerate certificate and compare
resource := &TorObfs4StateResource{} resource := &TorObfs4StateResource{}
expectedCert, err := resource.generateCertificate(nodeIdHex, publicKeyHex) expectedCert, err := resource.generateCertificate(nodeIdHex, publicKeyHex)
if err != nil { if err != nil {
return fmt.Errorf("Failed to generate expected certificate: %v", err) return fmt.Errorf("Failed to generate expected certificate: %v", err)
} }
if certificate != expectedCert { if certificate != expectedCert {
return fmt.Errorf("Certificate doesn't match expected value") return fmt.Errorf("Certificate doesn't match expected value")
} }
return nil return nil
} }
} }
@ -395,18 +395,18 @@ func testTorObfs4StateBridgeLineValidity(resourceName string) resource.TestCheck
if !ok { if !ok {
return fmt.Errorf("Resource not found: %s", resourceName) return fmt.Errorf("Resource not found: %s", resourceName)
} }
certificate := rs.Primary.Attributes["certificate"] certificate := rs.Primary.Attributes["certificate"]
iatMode := rs.Primary.Attributes["iat_mode"] iatMode := rs.Primary.Attributes["iat_mode"]
bridgeLine := rs.Primary.Attributes["bridge_line"] bridgeLine := rs.Primary.Attributes["bridge_line"]
// Expected bridge line format // Expected bridge line format
expectedBridgeLine := fmt.Sprintf("Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=%s iat-mode=%s", certificate, iatMode) expectedBridgeLine := fmt.Sprintf("Bridge obfs4 <IP:PORT> <FINGERPRINT> cert=%s iat-mode=%s", certificate, iatMode)
if bridgeLine != expectedBridgeLine { if bridgeLine != expectedBridgeLine {
return fmt.Errorf("Bridge line doesn't match expected format.\nExpected: %s\nActual: %s", expectedBridgeLine, bridgeLine) return fmt.Errorf("Bridge line doesn't match expected format.\nExpected: %s\nActual: %s", expectedBridgeLine, bridgeLine)
} }
return nil return nil
} }
} }
@ -417,12 +417,12 @@ func testTorObfs4StateResourcesAreDifferent(resource1, resource2 string) resourc
if !ok { if !ok {
return fmt.Errorf("Resource not found: %s", resource1) return fmt.Errorf("Resource not found: %s", resource1)
} }
rs2, ok := s.RootModule().Resources[resource2] rs2, ok := s.RootModule().Resources[resource2]
if !ok { if !ok {
return fmt.Errorf("Resource not found: %s", resource2) return fmt.Errorf("Resource not found: %s", resource2)
} }
// Check that crypto fields are different // Check that crypto fields are different
if rs1.Primary.Attributes["node_id"] == rs2.Primary.Attributes["node_id"] { if rs1.Primary.Attributes["node_id"] == rs2.Primary.Attributes["node_id"] {
return fmt.Errorf("Resources have same node_id") return fmt.Errorf("Resources have same node_id")
@ -439,12 +439,11 @@ func testTorObfs4StateResourcesAreDifferent(resource1, resource2 string) resourc
if rs1.Primary.Attributes["bridge_line"] == rs2.Primary.Attributes["bridge_line"] { if rs1.Primary.Attributes["bridge_line"] == rs2.Primary.Attributes["bridge_line"] {
return fmt.Errorf("Resources have same bridge_line") return fmt.Errorf("Resources have same bridge_line")
} }
return nil return nil
} }
} }
// Helper functions for creating types.String and types.Int64 values in tests // Helper functions for creating types.String and types.Int64 values in tests
func typeStringValue(value string) types.String { func typeStringValue(value string) types.String {
return types.StringValue(value) return types.StringValue(value)
@ -452,4 +451,4 @@ func typeStringValue(value string) types.String {
func typeInt64Value(value int64) types.Int64 { func typeInt64Value(value int64) types.Int64 {
return types.Int64Value(value) return types.Int64Value(value)
} }

View file

@ -185,4 +185,4 @@ func (r *TorRelayIdentityEd25519Resource) generateSha256Fingerprint(publicKey ed
publicKeyBytes, _ := x509.MarshalPKIXPublicKey(publicKey) publicKeyBytes, _ := x509.MarshalPKIXPublicKey(publicKey)
sha256Sum := sha256.Sum256(publicKeyBytes) sha256Sum := sha256.Sum256(publicKeyBytes)
return fmt.Sprintf("%x", sha256Sum) return fmt.Sprintf("%x", sha256Sum)
} }

View file

@ -37,4 +37,4 @@ func TestAccTorRelayIdentityEd25519Resource(t *testing.T) {
const testAccTorRelayIdentityEd25519ResourceConfig = ` const testAccTorRelayIdentityEd25519ResourceConfig = `
resource "tor_relay_identity_ed25519" "test" {} resource "tor_relay_identity_ed25519" "test" {}
` `

View file

@ -208,4 +208,4 @@ func (r *TorRelayIdentityRsaResource) generateFingerprints(publicKey *rsa.Public
sha256Fingerprint := fmt.Sprintf("%x", sha256Sum) sha256Fingerprint := fmt.Sprintf("%x", sha256Sum)
return sha1Fingerprint, sha256Fingerprint, nil return sha1Fingerprint, sha256Fingerprint, nil
} }

View file

@ -39,4 +39,4 @@ func TestAccTorRelayIdentityRsaResource(t *testing.T) {
const testAccTorRelayIdentityRsaResourceConfig = ` const testAccTorRelayIdentityRsaResourceConfig = `
resource "tor_relay_identity_rsa" "test" {} resource "tor_relay_identity_rsa" "test" {}
` `

View file

@ -48,4 +48,4 @@ func main() {
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal(err.Error())
} }
} }