diff --git a/README.md b/README.md index ddf7a1f..a08fc3d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Build with [Angular](https://angular.io) and [mdbootstrap](https://mdbootstrap.c ### Web UI abilities: | Kind | Create | List | Update | Delete | |--------------|:-----------------------|:-----------:|:-----------:|:-----------:| -| Bucket | V | V | add/remove events, change lifecycle, manage quota, tags, policy | V | +| Bucket | V | V | add/remove events, change lifecycle, manage quota, tags, policy, encryption | V | | User | V | V | update password, change policy | V | | Policy | V | V | V | V | | Group | V | V | add users to group, remove users, change policy | only if group is empty (has no members) | @@ -57,7 +57,7 @@ In real life cases you'll need to change this environment variables at `` Docker If you run multiple instances of [adminio-api](https://github.com/rzrbld/adminio-api) you can set `` ADMINIO_MULTI_BACKEND `` to ``true`` and fill `` ADMINIO_BACKENDS `` example with needed urls and names. Please note - in this case you still need points ``API_BASE_URL`` to one of this instances. And then build a docker image. #### Kubernetes/OpenShift/OKD/OCP -go to [Helm carts](https://github.com/rzrbld/adminio-helm) repo +go to [Helm chart](https://github.com/rzrbld/adminio-helm) repo #### npm build Method that described above also works if you build with `` npm run build ``. diff --git a/docker-compose.yml b/docker-compose.yml index 2e6ba2b..a546dbd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,7 +1,7 @@ version: '3' services: minio: - image: minio/minio:RELEASE.2020-11-13T20-10-18Z + image: minio/minio:RELEASE.2020-11-25T22-36-25Z ports: - "9000:9000" environment: @@ -9,7 +9,7 @@ services: MINIO_SECRET_KEY: testtest123 command: server /data0 /data1 /data2 /data3 adminio-ui: - image: rzrbld/adminio-ui:release-1.5 + image: rzrbld/adminio-ui:release-1.6 environment: API_BASE_URL: "http://localhost:8080" ADMINIO_MULTI_BACKEND: "false" @@ -18,11 +18,12 @@ services: ports: - "80:80" adminio-api: - image: rzrbld/adminio-api:release-1.5 + image: rzrbld/adminio-api:release-1.6 environment: MINIO_ACCESS: test MINIO_SECRET: testtest123 MINIO_HOST_PORT: minio:9000 + MINIO_SSE_MASTER_KEY: 1:da2f4cfa32bed76507dcd44b42872328a8e14f25cd2a1ec0fb85d299a192a447 ADMINIO_HOST_PORT: :8080 depends_on: - minio diff --git a/src/app/api.service.ts b/src/app/api.service.ts index 7f8f333..0feed5c 100644 --- a/src/app/api.service.ts +++ b/src/app/api.service.ts @@ -318,7 +318,6 @@ export class ApiService { return this.httpClient.post(this.baseUrl+'/api/v2/bucket/set-policy', form); } - public getBucketPolicy(bucketName){ let form = new FormData(); @@ -327,4 +326,31 @@ export class ApiService { return this.httpClient.post(this.baseUrl+'/api/v2/bucket/get-policy', form); } + public getBucketEncryption(bucketName){ + let form = new FormData(); + + form.append('bucketName', bucketName); + + return this.httpClient.post(this.baseUrl+'/api/v2/bucket/get-encryption', form); + } + + public setBucketEncryption(bucketName, encType, encMasterKeyID){ + let form = new FormData(); + + form.append('bucketName', bucketName); + form.append('bucketEncryptionType', encType); + form.append('kmsMasterKey', encMasterKeyID); + + return this.httpClient.post(this.baseUrl+'/api/v2/bucket/set-encryption', form); + } + + public removeBucketEncryption(bucketName){ + let form = new FormData(); + + form.append('bucketName', bucketName); + + return this.httpClient.post(this.baseUrl+'/api/v2/bucket/remove-encryption', form); + } + + } diff --git a/src/app/app.component.html b/src/app/app.component.html index ecba29a..53bd93e 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -70,7 +70,7 @@
- create issue or fork at github.com | v:1.5    + create issue or fork at github.com | v:1.6   
diff --git a/src/app/buckets/buckets.component.html b/src/app/buckets/buckets.component.html index e612161..3d3f3e1 100644 --- a/src/app/buckets/buckets.component.html +++ b/src/app/buckets/buckets.component.html @@ -31,6 +31,7 @@

Buckets

{{buckets[b].name}} +    {{buckets[b].policy}} @@ -94,11 +95,12 @@

Buckets

-   +         + @@ -130,8 +132,8 @@
@@ -192,7 +194,7 @@
+ + + + @@ -257,6 +282,16 @@ +
+
Encryption
+

+
+ +
+
Tags
@@ -355,6 +390,17 @@
+
+
+
Encryption
+

+
+ +
+
Tags
diff --git a/src/app/buckets/buckets.component.ts b/src/app/buckets/buckets.component.ts index 58e3df9..f6d98b6 100644 --- a/src/app/buckets/buckets.component.ts +++ b/src/app/buckets/buckets.component.ts @@ -19,25 +19,31 @@ export class BucketsComponent implements OnInit, AfterViewInit { bucketToDelete; bucketToRemoveNotifications; bucketToRemoveQuota; + bucketToRemoveEncryption; + updateEncryptionTypeChanged = false; editBucketName; newBucketName = ""; uiShowQuota = false; newBucketQuotaType = ""; newBucketQuota = ""; - quotaTypes = ["fifo", "hard"] + quotaTypes = ["fifo", "hard"]; serviceInfo; diskUsageInfo; + newBucketEncryption = ""; + encryptionTypes = ["sse-s3", "sse-kms"]; + newBucketMasterKeyID = ""; newBucketEventARN = ""; updateBucketEventARN = ""; updateBucketEventFilterPrefix = ""; updateBucketEventFilterSuffix = ""; updateBucketQuotaObj = {}; + updateBucketEncryptionObj = {}; updateQuotaTypeChanged = false; updateQuotaChanged = false; newBucketPolicy = "none"; // updateBucketPolicy = "none" - policyTypes = ["none", "upload", "download", "public", "custom"] + policyTypes = ["none", "upload", "download", "public", "custom"]; updatePolicyTypeChanged = false; uploadPolicyName; uploadPolicyFile; @@ -196,6 +202,27 @@ export class BucketsComponent implements OnInit, AfterViewInit { } }); + this.apiService.getBucketEncryption(bucketName).subscribe((data)=>{ + this.apiService.validateAuthInResponse(data) + console.log(Object.keys(data)); + console.log(data); + + var dataKeys = Object.keys(data); + console.log("Bucket Encryption >>",dataKeys[1]); + if(dataKeys[1]=="Rules"){ + this.updateBucketEncryptionObj = data; + var dataVals = Object.values(data); + console.log("Enc datavals", dataVals[1][0]['Apply']['KmsMasterKeyID']) + if(dataVals[1][0]['Apply']['KmsMasterKeyID'] == ""){ + this.updateBucketEncryptionObj = "sse-s3" + }else{ + this.updateBucketEncryptionObj = "sse-kms" + } + }else{ + this.updateBucketEncryptionObj = ""; + } + }); + this.apiService.getBucketQuota(bucketName).subscribe((data)=>{ this.apiService.validateAuthInResponse(data) console.log(Object.keys(data)); @@ -233,10 +260,18 @@ export class BucketsComponent implements OnInit, AfterViewInit { this.updatePolicyTypeChanged = true; } + private updateEncryptionType(){ + this.updateEncryptionTypeChanged = true; + } + private updateQuota(){ this.updateQuotaChanged = true; } + private deleteBucketEncryptionPrepare(bucketName){ + this.bucketToRemoveEncryption = bucketName; + } + private deleteBucket(){ this.apiService.deleteBucket(this.bucketToDelete).subscribe((data)=>{ this.apiService.validateAuthInResponse(data) @@ -253,6 +288,9 @@ export class BucketsComponent implements OnInit, AfterViewInit { private resetForm(){ this.newBucketName = ""; this.newBucketEventARN = ""; + this.newBucketEncryption = ""; + this.newBucketMasterKeyID = ""; + this.updateEncryptionTypeChanged = false; this.newBucketEventFilterPrefix = ""; this.newBucketEventFilterSuffix = ""; this.selectedEventTypes = []; @@ -269,10 +307,14 @@ export class BucketsComponent implements OnInit, AfterViewInit { private resetUpdateForm() { this.updateBucketEventARN = ""; + this.newBucketEncryption = ""; + this.newBucketMasterKeyID = ""; + this.updateEncryptionTypeChanged = false; this.selectedEventTypes = []; this.updateBucketEventFilterPrefix = ""; this.updateBucketEventFilterSuffix = ""; this.updateBucketQuotaObj = {}; + this.updateBucketEncryptionObj = ""; this.updateQuotaTypeChanged = false; this.updateQuotaChanged = false; this.tagListChanged = false; @@ -339,11 +381,11 @@ export class BucketsComponent implements OnInit, AfterViewInit { var bucketsArr = this.newBucketName.split(',') for (var i = 0; i < bucketsArr.length; i++) { if(bucketsArr[i]!=''){ - this.createBucketSimple(bucketsArr[i],this.newBucketEventARN,this.newBucketQuotaType,this.newBucketQuota,this.newBucketPolicy,bucketsArr.length,i+1) + this.createBucketSimple(bucketsArr[i],this.newBucketEventARN,this.newBucketQuotaType,this.newBucketQuota,this.newBucketPolicy,this.newBucketEncryption,this.newBucketMasterKeyID, bucketsArr.length,i+1) } } }else{ - this.createBucketSimple(this.newBucketName,this.newBucketEventARN,this.newBucketQuotaType,this.newBucketQuota,this.newBucketPolicy,1,1) + this.createBucketSimple(this.newBucketName,this.newBucketEventARN,this.newBucketQuotaType,this.newBucketQuota,this.newBucketPolicy,this.newBucketEncryption,this.newBucketMasterKeyID,1,1) } } @@ -377,9 +419,14 @@ export class BucketsComponent implements OnInit, AfterViewInit { if(this.updateQuotaTypeChanged || this.updateQuotaChanged){ this.setQuotaForBucket(this.editBucketName, quotaType, quotaVal, true) } + if(this.updatePolicyTypeChanged){ this.setPolicy(this.editBucketName, true) } + + if(this.updateEncryptionTypeChanged){ + this.setBucketEncryption(this.editBucketName, this.updateBucketEncryptionObj, this.newBucketMasterKeyID, true) + } } private enableNotificationForBucket(bucket, stsARN, eventTypes, filterPrefix, filterSuffix, updateListAfter){ @@ -442,7 +489,38 @@ export class BucketsComponent implements OnInit, AfterViewInit { }); } - private createBucketSimple(bucket, eventARN, quotaType, quotaVal, policy, numberOfBuckets, currentBucketNumber){ + private removeBucketEncryption(){ + var bucket = this.bucketToRemoveEncryption; + this.apiService.removeBucketEncryption(bucket).subscribe((data)=>{ + this.apiService.validateAuthInResponse(data) + console.log(data); + if(data["Success"]){ + this.toastr.success('Encryption for bucket '+bucket+' has been removed', 'Success'); + }else{ + this.toastr.error(JSON.stringify(data), 'Error while removing bucket encryption'); + } + this.getBuckets(); + }); + } + + + private setBucketEncryption(bucket, encType, masterKeyID, reloadBucketList){ + this.apiService.setBucketEncryption(bucket, encType, masterKeyID).subscribe((data)=>{ + this.apiService.validateAuthInResponse(data) + if(data["Success"]){ + this.toastr.success('Encryption for bucket '+bucket+' has been set', 'Success'); + }else{ + this.toastr.error(JSON.stringify(data), 'Error while set encryption for bucket'); + } + if(reloadBucketList){ + this.getBuckets(); + } + }); + } + + + + private createBucketSimple(bucket, eventARN, quotaType, quotaVal, policy, encryption, masterKeyID, numberOfBuckets, currentBucketNumber){ this.apiService.createBucket(bucket).subscribe((data)=>{ this.apiService.validateAuthInResponse(data) console.log(data); @@ -460,6 +538,9 @@ export class BucketsComponent implements OnInit, AfterViewInit { if(this.updatePolicyTypeChanged){ this.setPolicy(bucket, false) } + if(encryption != ""){ + this.setBucketEncryption(bucket, encryption, masterKeyID, false) + } }else{ this.toastr.error(JSON.stringify(data), 'Error while creating bucket'); } @@ -497,7 +578,9 @@ export class BucketsComponent implements OnInit, AfterViewInit { // this.toastr.error("Bucket has no lifecycle", 'Error while getting lifecycle'); }else{ this.downloadLifecycleAvailable = 1; - var uri = this.sanitizer.bypassSecurityTrustUrl("data:text/xml;charset=UTF-8," + encodeURIComponent(data.toString())); + console.log("Lifecycle>>>>",JSON.stringify(data)); + + var uri = this.sanitizer.bypassSecurityTrustUrl("data:text/json;charset=UTF-8," + encodeURIComponent(JSON.stringify(data))); this.downloadJsonHref = uri; } }