Wednesday 26 August 2020

Set rotation period to NEVER for all crypto keys in one Google KMS keyring

Sometimes when a number of crypto keys was created it's needed to prevent them from generating new versions. See also How to delete all key versions in Google KMS keyring


 

import com.google.cloud.kms.v1.CryptoKey;

import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.kms.v1.KeyRingName;
import com.google.protobuf.Duration;
import com.google.protobuf.FieldMask;
import com.google.protobuf.util.FieldMaskUtil;

import java.io.IOException;

public class Cleanup {

private static final String KMS_PROJECT_ID = "my-dev-project";
private static final String KMS_LOCATION = "global";
private static final String KMS_KEYRING = "encrypted-values";

public static void main(String[] args) {
try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) {
String keyRingName = KeyRingName.format(KMS_PROJECT_ID, KMS_LOCATION, KMS_KEYRING);
for (CryptoKey cryptoKey : client.listCryptoKeys(keyRingName).iterateAll()) {
String name = cryptoKey.getName();
Duration rotation = cryptoKey.getRotationPeriod();
if (rotation.getNanos() != 0 || rotation.getSeconds() != 0) {
System.out.println("Clearing rotation period of " + name);
CryptoKey updatedKey = CryptoKey.newBuilder(cryptoKey)
.clearRotationPeriod()
.clearNextRotationTime()
.build();
FieldMask fieldMask = FieldMaskUtil.fromString("rotation_period,next_rotation_time");
client.updateCryptoKey(updatedKey, fieldMask);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}

}

Wednesday 14 August 2019

Delete all key versions in Google KMS keyring

After some experiments with Google KMS I found that I have a few thousands keys created. Unfortunately there's no option in the google cloud console to destroy all keys in the key ring, the only thing possible to do is to "Disable all key versions" on each version by hand, which is not very exciting job to do with thousands of them. After short thinking I came out with the following simple java program which destroying all key versions in the keyring:

import com.google.cloud.kms.v1.KeyManagementServiceClient;
import com.google.cloud.kms.v1.KeyRingName;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;

public class CleanupKmsKeys {

private static final String KMS_PROJECT_ID = "my-development-project";

private static final String KMS_LOCATION = "global";

private static final String KMS_KEYRING = "encrypted-values";
// Destroy all key versions in {@link #KMS_KEYRING}
public static void
main(String[] args) { String keyRingName = KeyRingName.format(KMS_PROJECT_ID, KMS_LOCATION, KMS_KEYRING); warinig(keyRingName); AtomicInteger keyCount = new AtomicInteger(0); AtomicInteger keyVersionCount = new AtomicInteger(0); try (KeyManagementServiceClient client = KeyManagementServiceClient.create()) { client.listCryptoKeys(keyRingName).iterateAll().forEach(cryptoKey -> { String name = cryptoKey.getName(); client.listCryptoKeyVersions(name).iterateAll().forEach(cryptKeyVer -> { if ( !cryptKeyVer.hasDestroyTime() && !cryptKeyVer.hasDestroyEventTime() ) { String cryptoKeyVersionName = cryptKeyVer.getName(); client.destroyCryptoKeyVersion(cryptoKeyVersionName); System.out.println(String.format( "Destroyed version %s of key %s", name, cryptoKey )); keyVersionCount.getAndIncrement(); } }); keyCount.getAndIncrement(); }); System.out.println(String.format( "Deleted %d keys and %d versions", keyCount.get(), keyVersionCount.get() )); } catch (IOException e) { System.out.println(String.format( "Failed to delete all versions, deleted %d keys and %d versions", keyCount.get(), keyVersionCount.get() )); throw new RuntimeException("Failed to destroy KMS keys"); } } private static void warinig(String keyRingName) { try { System.out.println(String.format( "I'm going to destroy all keys in %s", keyRingName )); Thread.sleep(1000); System.out.println("In 3 seconds"); Thread.sleep(1000); System.out.println("In 2 seconds"); Thread.sleep(1000); System.out.println("In 1 second"); Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException("Something went wrong"); } } }

Tuesday 30 July 2019

Running unit tests in idea with Pattern

For some reason it's not quite documented what the "Test Kind: Pattern" in the test run configuration of the IntelliJ IDEA.
It is simply a regex expression for the classname, for example if it's needed to run all classes in the module ending up with Test then the Pattern should be the following regular expression:

^.*Test$

Wednesday 10 July 2019

Spaghetti code

There's a million of articles explaining why one should not write the Spaghetti code, however software implementations with all kinds of rotten Spaghetti are really numerous, the function spaghetti code in particular.

What is the difference of function spaghetti code from usual spaghetti code? Whereas a classic spaghetti code consists of a combination of goto, conditions, if-clauses and so on; the function spaghetti kind of code usually consists of single source file filled with all possible kinds of functions which do absolutely anything. The source file of 4000 (four thousands) lines is kind of a norm in the software development industry nowadays, I personally seen source files with more than 15000 (fifteen thousands lines of code).

It is very common for JavaScript, not because the language is particularly bad, just because a lot of development is done with JavaScript, and it's often done not by best developers. Nevertheless, the Java classes with hundreds of methods, python files with heaps of functions irrelevant to each other, the PHP files doing everything are also quite common.

There's absolutely no excuse to keep these giants on the back-end, so back-enders simply make a sad face and admit that they write bad code. JS developers are often more persistent in protecting their noodles, and have many excuses to dig these enormously deep function draw-wells, some excuses them are:

  • We don't want many separate JavaScript files because single one loads faster;
  • We don't want another build tool which would transpile our JavaScript into single or a few build files;
  • We don't want to use NPM;
  • Our company proxy blocking NPM downloads;
  • These are just a tiny little functions, all irrelevant to each others, let's keep 'em in one place;
  • We don't know how to write proper JS. 
All these excuses are just rubbish, if you are capable to install packages with NPM this problem is easily solved with such things as Rollup, Webpack, Babel and Browserify.

If use of NPM is for some mysterious reason is absolutely impossible, these functions anyway can be somehow grouped by the subject and split into a few files, those could be fed to the browser as they are, or can be simply concatenated into one file with any kind of build tool.

Friday 24 May 2019

Remove merged local branches (git)

This command executed in in project directory with bash will delete all local branches which were already merged into master:
git branch --merged | egrep -v "(^\*|master)" | xargs git branch -d

Explanation:
git branch --merged - list all merged branches
egrep -v "(^\*|master)" - grep "master" from provided lines one by one (piped from git branch above)
xargs git branch -d - delete filtered branches (piped from egrep above)

Same sort of command in PowerShell:

git branch --merged main | ForEach-Object { if ($_  -ne '* main' -and $_ -ne '* master') { git branch -d $_.trim() } }

Saturday 30 June 2018

Diff two files with powershell

Compare-Object -ReferenceObject $(Get-Content f1.txt) -DifferenceObject $(Get-Content f2.txt)

Friday 5 January 2018

wicket:message with links and labels inside

wicket:message can contain markup inside of itself. It is an easy thing to do, but not quite obvious that it's allowed to do that.

For example wicket:message with a link and a label:

MyPanel.html
<wicket:message key="myMessage">
    <span wicket:id="myLabel" />
    <a wicket:id="myLink" />
</wicket:message>

MyPanel.java
//...
add(new Label("myLabel", myLabelModel));
add(new LabelledBookmarkablePageLink("myLink", ViewSomethingPage.class));
//...

MyPanel.properties
myMessage = a text before a label ${myLabel}, between label and a link ${myLink}, after link
myLink= My Link Text

${myLabel} and ${myLink} of myMessage will be replaced with appropriate components