Skip to content

Commit a6bc47a

Browse files
authored
Merge pull request #20 from trendmicro/update_to_latest_version_v1.6.1
update to latest version: v1.6.1
2 parents e6ba4c8 + 4609319 commit a6bc47a

File tree

6 files changed

+259
-32
lines changed

6 files changed

+259
-32
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# CHANGELOG
22

3+
## 1.6.1 - 2025-09-11
4+
5+
* Add customized cloud account id setting via `SetCloudAccountID` function
6+
37
## 1.6.0 - 2025-06-30
48

59
* Add active content detection support via `SetActiveContentEnable` function

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,21 @@ You can disable digest calculation by calling the `SetDigestDisable` function:
214214
client.SetDigestDisable()
215215
```
216216

217+
### Set Cloud Account ID
218+
219+
You can set a cloud account ID that will be automatically appended to all scan tags in the format `cloudAccountId=value`:
220+
221+
```go
222+
err := client.SetCloudAccountID("633537927402")
223+
if err != nil {
224+
// Handle error - cloudAccountID too long
225+
}
226+
```
227+
228+
**Note**:
229+
- The total tag length (including `cloudAccountId=` prefix) cannot exceed 63 characters
230+
- Using cloud account ID occupies one tag slot, reducing max customer tags from 8 to 7
231+
217232
## Golang Client SDK API Reference
218233

219234
### ```func NewClient(key string, region string) (c *AmaasClient, e error)```

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.6.0
1+
1.6.1

grpc.go

Lines changed: 72 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -218,21 +218,22 @@ func (reader *AmaasClientBufferReader) Hash(algorithm string) (string, error) {
218218
///////////////////////////////////////
219219

220220
type AmaasClient struct {
221-
conn *grpc.ClientConn
222-
isC1Token bool
223-
authKey string
224-
addr string
225-
useTLS bool
226-
caCert string
227-
verifyCert bool
228-
timeoutSecs int
229-
appName string
230-
archHandler AmaasClientArchiveHandler
231-
pml bool
232-
feedback bool
233-
verbose bool
234-
activeContent bool
235-
digest bool
221+
conn *grpc.ClientConn
222+
isC1Token bool
223+
authKey string
224+
addr string
225+
useTLS bool
226+
caCert string
227+
verifyCert bool
228+
timeoutSecs int
229+
appName string
230+
archHandler AmaasClientArchiveHandler
231+
pml bool
232+
feedback bool
233+
verbose bool
234+
activeContent bool
235+
digest bool
236+
cloudAccountID string
236237
}
237238

238239
func getHashValue(dataReader AmaasClientReader) (string, string, error) {
@@ -446,8 +447,7 @@ func runUploadLoop(stream pb.Scan_RunClient, dataReader AmaasClientReader, bulk
446447
return
447448
}
448449

449-
func (ac *AmaasClient) bufferScanRun(buffer []byte, identifier string, tags []string) (string, error) {
450-
450+
func (ac *AmaasClient) bufferScanRun(ctx context.Context, buffer []byte, identifier string, tags []string) (string, error) {
451451
if ac.conn == nil {
452452
return "", makeInternalError(MSG("MSG_ID_ERR_CLIENT_NOT_READY"))
453453
}
@@ -458,18 +458,20 @@ func (ac *AmaasClient) bufferScanRun(buffer []byte, identifier string, tags []st
458458
}
459459
defer bufferReader.Close()
460460

461-
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(ac.timeoutSecs))
461+
ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(ac.timeoutSecs))
462462

463463
ctx = ac.buildAuthContext(ctx)
464464

465465
ctx = ac.buildAppNameContext(ctx)
466466

467-
return scanRun(ctx, cancel, pb.NewScanClient(ac.conn), bufferReader, tags, ac.pml, true, ac.feedback,
467+
tags = ac.appendCloudAccountIDToTags(tags)
468+
469+
return scanRun(ctx, cancel, pb.NewScanClient(ac.conn), bufferReader,
470+
tags, ac.pml, true, ac.feedback,
468471
ac.verbose, ac.activeContent, ac.digest)
469472
}
470473

471-
func (ac *AmaasClient) fileScanRun(fileName string, tags []string) (string, error) {
472-
474+
func (ac *AmaasClient) fileScanRun(ctx context.Context, fileName string, tags []string) (string, error) {
473475
if ac.conn == nil {
474476
return "", makeInternalError(MSG("MSG_ID_ERR_CLIENT_NOT_READY"))
475477
}
@@ -478,40 +480,46 @@ func (ac *AmaasClient) fileScanRun(fileName string, tags []string) (string, erro
478480
return ac.archHandler.fileScanRun(fileName)
479481
}
480482

481-
return ac.fileScanRunNormalFile(fileName, tags)
483+
return ac.fileScanRunNormalFile(ctx, fileName, tags)
482484
}
483485

484-
func (ac *AmaasClient) fileScanRunNormalFile(fileName string, tags []string) (string, error) {
486+
func (ac *AmaasClient) fileScanRunNormalFile(ctx context.Context, fileName string, tags []string) (string, error) {
485487

486488
fileReader, err := InitFileReader(fileName)
487489
if err != nil {
488490
return "", makeInternalError(fmt.Sprintf(MSG("MSG_ID_ERR_CLIENT_ERROR"), err.Error()))
489491
}
490492
defer fileReader.Close()
491493

492-
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(ac.timeoutSecs))
494+
ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(ac.timeoutSecs))
493495

494496
ctx = ac.buildAuthContext(ctx)
495497

496498
ctx = ac.buildAppNameContext(ctx)
497499

498-
return scanRun(ctx, cancel, pb.NewScanClient(ac.conn), fileReader, tags, ac.pml, true, ac.feedback,
500+
tags = ac.appendCloudAccountIDToTags(tags)
501+
502+
return scanRun(ctx, cancel, pb.NewScanClient(ac.conn), fileReader,
503+
tags, ac.pml, true, ac.feedback,
499504
ac.verbose, ac.activeContent, ac.digest)
500505
}
501506

502-
func (ac *AmaasClient) readerScanRun(reader AmaasClientReader, tags []string) (string, error) {
507+
func (ac *AmaasClient) readerScanRun(ctx context.Context, reader AmaasClientReader, tags []string) (string, error) {
503508

504509
if ac.conn == nil {
505510
return "", makeInternalError(MSG("MSG_ID_ERR_CLIENT_NOT_READY"))
506511
}
507512

508-
ctx, cancel := context.WithTimeout(context.Background(), time.Second*time.Duration(ac.timeoutSecs))
513+
ctx, cancel := context.WithTimeout(ctx, time.Second*time.Duration(ac.timeoutSecs))
509514

510515
ctx = ac.buildAuthContext(ctx)
511516

512517
ctx = ac.buildAppNameContext(ctx)
513518

514-
return scanRun(ctx, cancel, pb.NewScanClient(ac.conn), reader, tags, ac.pml, true, ac.feedback,
519+
tags = ac.appendCloudAccountIDToTags(tags)
520+
521+
return scanRun(ctx, cancel, pb.NewScanClient(ac.conn), reader,
522+
tags, ac.pml, true, ac.feedback,
515523
ac.verbose, ac.activeContent, ac.digest)
516524
}
517525

@@ -1127,6 +1135,22 @@ func (ac *AmaasClient) SetDigestDisable() {
11271135
ac.digest = false
11281136
}
11291137

1138+
func (ac *AmaasClient) SetCloudAccountID(cloudAccountID string) error {
1139+
if cloudAccountID == "" {
1140+
ac.cloudAccountID = cloudAccountID
1141+
return nil
1142+
}
1143+
1144+
// Calculate the total tag length with "cloudAccountId=" prefix
1145+
cloudAccountTag := fmt.Sprintf("cloudAccountId=%s", cloudAccountID)
1146+
if len(cloudAccountTag) > maxTagSize {
1147+
return fmt.Errorf("cloudAccountID tag 'cloudAccountId=%s' exceeds maximum tag size of %d characters", cloudAccountID, maxTagSize)
1148+
}
1149+
1150+
ac.cloudAccountID = cloudAccountID
1151+
return nil
1152+
}
1153+
11301154
func validateTags(tags []string) error {
11311155
if len(tags) == 0 {
11321156
return errors.New("tags cannot be empty")
@@ -1146,3 +1170,23 @@ func validateTags(tags []string) error {
11461170
}
11471171
return nil
11481172
}
1173+
1174+
func (ac *AmaasClient) appendCloudAccountIDToTags(tags []string) []string {
1175+
if ac.cloudAccountID == "" {
1176+
return tags
1177+
}
1178+
1179+
cloudAccountTag := fmt.Sprintf("cloudAccountId=%s", ac.cloudAccountID)
1180+
1181+
// Check if the cloudAccountTag exceeds maxTagSize (63 characters)
1182+
if len(cloudAccountTag) > maxTagSize {
1183+
logMsg(LogLevelWarning, "cloudAccountId tag exceeds maximum tag size (%d), skipping", maxTagSize)
1184+
return tags
1185+
}
1186+
1187+
if tags == nil {
1188+
return []string{cloudAccountTag}
1189+
}
1190+
1191+
return append(tags, cloudAccountTag)
1192+
}

grpc_client_test.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,3 +642,149 @@ func generateJwtToken() (string, error) {
642642

643643
return ss, nil
644644
}
645+
646+
//
647+
// CloudAccountID related tests
648+
//
649+
650+
func TestSetCloudAccountIDValid(t *testing.T) {
651+
ac := &AmaasClient{}
652+
653+
// Test with AWS account ID (12 digits)
654+
err := ac.SetCloudAccountID("633537927402")
655+
assert.Nil(t, err)
656+
assert.Equal(t, "633537927402", ac.cloudAccountID)
657+
658+
// Test with Azure UUID-v4 (36 characters)
659+
err = ac.SetCloudAccountID("a47ac10b-58cc-4372-a567-0e02b2c3d479")
660+
assert.Nil(t, err)
661+
assert.Equal(t, "a47ac10b-58cc-4372-a567-0e02b2c3d479", ac.cloudAccountID)
662+
663+
// Test with exactly 48 characters (63 - 15 for "cloudAccountId=")
664+
longButValid := "123456789012345678901234567890123456789012345678"
665+
err = ac.SetCloudAccountID(longButValid)
666+
assert.Nil(t, err)
667+
assert.Equal(t, longButValid, ac.cloudAccountID)
668+
}
669+
670+
func TestSetCloudAccountIDTooLong(t *testing.T) {
671+
ac := &AmaasClient{}
672+
673+
// Test with string longer than 48 characters (49 chars)
674+
tooLong := "1234567890123456789012345678901234567890123456789"
675+
err := ac.SetCloudAccountID(tooLong)
676+
assert.NotNil(t, err)
677+
assert.Contains(t, err.Error(), "exceeds maximum tag size of 63 characters")
678+
assert.Equal(t, "", ac.cloudAccountID)
679+
}
680+
681+
func TestSetCloudAccountIDEmpty(t *testing.T) {
682+
ac := &AmaasClient{}
683+
684+
// Test with empty string (should be allowed)
685+
err := ac.SetCloudAccountID("")
686+
assert.Nil(t, err)
687+
assert.Equal(t, "", ac.cloudAccountID)
688+
}
689+
690+
func TestAppendCloudAccountIDToTagsWithEmpty(t *testing.T) {
691+
ac := &AmaasClient{}
692+
ac.cloudAccountID = ""
693+
694+
// Test with nil tags
695+
result := ac.appendCloudAccountIDToTags(nil)
696+
assert.Nil(t, result)
697+
698+
// Test with empty tags slice
699+
tags := []string{}
700+
result = ac.appendCloudAccountIDToTags(tags)
701+
assert.Equal(t, tags, result)
702+
703+
// Test with existing tags
704+
tags = []string{"tag1", "tag2"}
705+
result = ac.appendCloudAccountIDToTags(tags)
706+
assert.Equal(t, tags, result)
707+
}
708+
709+
func TestAppendCloudAccountIDToTagsWithValue(t *testing.T) {
710+
ac := &AmaasClient{}
711+
ac.cloudAccountID = "633537927402"
712+
713+
// Test with nil tags
714+
result := ac.appendCloudAccountIDToTags(nil)
715+
expected := []string{"cloudAccountId=633537927402"}
716+
assert.Equal(t, expected, result)
717+
718+
// Test with empty tags slice
719+
tags := []string{}
720+
result = ac.appendCloudAccountIDToTags(tags)
721+
expected = []string{"cloudAccountId=633537927402"}
722+
assert.Equal(t, expected, result)
723+
724+
// Test with existing tags
725+
tags = []string{"tag1", "tag2"}
726+
result = ac.appendCloudAccountIDToTags(tags)
727+
expected = []string{"tag1", "tag2", "cloudAccountId=633537927402"}
728+
assert.Equal(t, expected, result)
729+
}
730+
731+
func TestAppendCloudAccountIDToTagsImmutability(t *testing.T) {
732+
ac := &AmaasClient{}
733+
ac.cloudAccountID = "633537927402"
734+
735+
// Test that original tags slice is not modified
736+
originalTags := []string{"tag1", "tag2"}
737+
originalTagsCopy := make([]string, len(originalTags))
738+
copy(originalTagsCopy, originalTags)
739+
740+
result := ac.appendCloudAccountIDToTags(originalTags)
741+
742+
// Original slice should remain unchanged
743+
assert.Equal(t, originalTagsCopy, originalTags)
744+
// Result should contain cloudAccountID
745+
expected := []string{"tag1", "tag2", "cloudAccountId=633537927402"}
746+
assert.Equal(t, expected, result)
747+
}
748+
749+
func TestCloudAccountIDIntegrationWithScanMethods(t *testing.T) {
750+
// Create a mock AmaasClient with connection set to nil (to trigger early return)
751+
ac := &AmaasClient{
752+
conn: nil,
753+
}
754+
755+
// Set cloudAccountID
756+
err := ac.SetCloudAccountID("633537927402")
757+
assert.Nil(t, err)
758+
759+
// Test ScanFile with cloudAccountID
760+
_, err = ac.ScanFile("nonexistent.txt", []string{"tag1"})
761+
assert.NotNil(t, err)
762+
assert.Contains(t, err.Error(), "Client is not ready")
763+
764+
// Test ScanBuffer with cloudAccountID
765+
_, err = ac.ScanBuffer([]byte("test"), "buffer", []string{"tag1"})
766+
assert.NotNil(t, err)
767+
assert.Contains(t, err.Error(), "Client is not ready")
768+
769+
// Test ScanReader with cloudAccountID
770+
bufferReader, _ := InitBufferReader([]byte("test"), "reader")
771+
_, err = ac.ScanReader(bufferReader, []string{"tag1"})
772+
assert.NotNil(t, err)
773+
assert.Contains(t, err.Error(), "Client is not ready")
774+
775+
bufferReader.Close()
776+
}
777+
778+
func TestAppendCloudAccountIDToTagsTooLong(t *testing.T) {
779+
ac := &AmaasClient{}
780+
781+
// Set a cloudAccountID that would make the tag too long (49 characters)
782+
ac.cloudAccountID = "1234567890123456789012345678901234567890123456789" // 49 chars
783+
784+
// Test with existing tags - should skip the cloudAccountID
785+
tags := []string{"tag1", "tag2"}
786+
result := ac.appendCloudAccountIDToTags(tags)
787+
788+
// Should return original tags unchanged (cloudAccountID skipped due to length)
789+
assert.Equal(t, tags, result)
790+
}

sdk.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,18 +98,36 @@ func (ac *AmaasClient) Destroy() {
9898
//
9999

100100
func (ac *AmaasClient) ScanFile(filePath string, tags []string) (resp string, e error) {
101+
ctx := context.Background()
101102
currentLogLevel = getLogLevel()
102-
return ac.fileScanRun(filePath, tags)
103+
return ac.fileScanRun(ctx, filePath, tags)
104+
}
105+
106+
func (ac *AmaasClient) ScanFileWithContext(ctx context.Context, filePath string, tags []string) (resp string, e error) {
107+
currentLogLevel = getLogLevel()
108+
return ac.fileScanRun(ctx, filePath, tags)
103109
}
104110

105111
func (ac *AmaasClient) ScanBuffer(buffer []byte, identifier string, tags []string) (resp string, e error) {
112+
ctx := context.Background()
106113
currentLogLevel = getLogLevel()
107-
return ac.bufferScanRun(buffer, identifier, tags)
114+
return ac.bufferScanRun(ctx, buffer, identifier, tags)
115+
}
116+
117+
func (ac *AmaasClient) ScanBufferWithContext(ctx context.Context, buffer []byte, identifier string, tags []string) (resp string, e error) {
118+
currentLogLevel = getLogLevel()
119+
return ac.bufferScanRun(ctx, buffer, identifier, tags)
108120
}
109121

110122
func (ac *AmaasClient) ScanReader(reader AmaasClientReader, tags []string) (resp string, e error) {
123+
ctx := context.Background()
124+
currentLogLevel = getLogLevel()
125+
return ac.readerScanRun(ctx, reader, tags)
126+
}
127+
128+
func (ac *AmaasClient) ScanReaderWithContext(ctx context.Context, reader AmaasClientReader, tags []string) (resp string, e error) {
111129
currentLogLevel = getLogLevel()
112-
return ac.readerScanRun(reader, tags)
130+
return ac.readerScanRun(ctx, reader, tags)
113131
}
114132

115133
func (ac *AmaasClient) DumpConfig() (output string) {

0 commit comments

Comments
 (0)