001package org.kuali.common.util.ssh.model;
002
003import org.kuali.common.util.Assert;
004import org.kuali.common.util.enc.EncUtils;
005import org.kuali.common.util.enc.EncryptionService;
006import org.kuali.common.util.nullify.NullUtils;
007import org.kuali.common.util.spring.SpringUtils;
008import org.kuali.common.util.spring.env.EnvUtils;
009import org.kuali.common.util.spring.env.EnvironmentService;
010
011import com.google.common.base.Optional;
012
013public final class KeyPair {
014
015        public String getName() {
016                return name;
017        }
018
019        public Optional<String> getPublicKey() {
020                return publicKey;
021        }
022
023        public Optional<String> getPrivateKey() {
024                return privateKey;
025        }
026
027        public Optional<String> getFingerprint() {
028                return fingerprint;
029        }
030
031        private final String name;
032        private final Optional<String> publicKey;
033        private final Optional<String> privateKey;
034        private final Optional<String> fingerprint;
035
036        private KeyPair(Builder builder) {
037                this.name = builder.name;
038                this.publicKey = builder.publicKey;
039                this.privateKey = builder.privateKey;
040                this.fingerprint = builder.fingerprint;
041        }
042
043        public static class Builder {
044
045                // Required
046                private final String name; // No default
047                private final Optional<EnvironmentService> env; // Defaults to Optional.absent() if not supplied
048                private final Optional<EncryptionService> enc; // Defaults to Optional.absent() if not supplied
049
050                // Optional
051                private Optional<String> publicKey = Optional.absent();
052                private Optional<String> privateKey = Optional.absent();
053                private Optional<String> fingerprint = Optional.absent();
054
055                private static final String NAME_KEY = "ssh.keyName";
056                private static final String PUBLIC_KEY = "ssh.publicKey";
057                private static final String PRIVATE_KEY = "ssh.privateKey";
058                private static final String FINGERPRINT_KEY = "ssh.fingerprint";
059
060                public Builder(String name) {
061                        this(EnvUtils.ABSENT, EncUtils.ABSENT, name);
062                }
063
064                public Builder(EnvironmentService env, String name) {
065                        this(Optional.of(env), EncUtils.ABSENT, name);
066                }
067
068                public Builder(EnvironmentService env, EncryptionService enc, String name) {
069                        this(Optional.of(env), Optional.of(enc), name);
070                }
071
072                public Builder(EnvironmentService env, KeyPair provided) {
073                        this(Optional.of(env), EncUtils.ABSENT, provided.getName());
074                        initialize(provided);
075                }
076
077                public Builder(EnvironmentService env, EncryptionService enc, KeyPair provided) {
078                        this(Optional.of(env), Optional.of(enc), provided.getName());
079                        initialize(provided);
080                }
081
082                private Builder(Optional<EnvironmentService> env, Optional<EncryptionService> enc, String name) {
083                        if (env.isPresent()) {
084                                this.name = env.get().getString(NAME_KEY, name);
085                        } else {
086                                this.name = name;
087                        }
088                        this.env = env;
089                        this.enc = enc;
090                }
091
092                public Builder publicKey(String publicKey) {
093                        this.publicKey = NullUtils.toAbsent(publicKey);
094                        return this;
095                }
096
097                public Builder privateKey(String privateKey) {
098                        this.privateKey = NullUtils.toAbsent(privateKey);
099                        return this;
100                }
101
102                public Builder fingerprint(String fingerprint) {
103                        this.fingerprint = NullUtils.toAbsent(fingerprint);
104                        return this;
105                }
106
107                private void initialize(KeyPair provided) {
108                        publicKey(provided.getPublicKey().orNull());
109                        privateKey(provided.getPrivateKey().orNull());
110                        fingerprint(provided.getFingerprint().orNull());
111                }
112
113                private void override() {
114                        if (env.isPresent()) {
115                                publicKey(SpringUtils.getString(env.get(), PUBLIC_KEY, publicKey).orNull());
116                                privateKey(SpringUtils.getString(env.get(), PRIVATE_KEY, privateKey).orNull());
117                                fingerprint(SpringUtils.getString(env.get(), FINGERPRINT_KEY, fingerprint).orNull());
118                        }
119                }
120
121                private void finish() {
122                        override();
123                        privateKey(EncUtils.decrypt(enc, privateKey).orNull());
124                }
125
126                private void validate(KeyPair pair, boolean assertDecryptedPrivateKey) {
127                        Assert.noBlanks(pair.getName());
128                        Assert.noNulls(pair.getPublicKey(), pair.getPrivateKey(), pair.getFingerprint());
129                        Assert.noBlanks(pair.getPublicKey(), pair.getPrivateKey(), pair.getFingerprint());
130                        if (assertDecryptedPrivateKey && pair.getPrivateKey().isPresent()) {
131                                Assert.notEncrypted(pair.getPrivateKey().get());
132                        }
133                }
134
135                public KeyPair build() {
136                        finish();
137                        boolean assertDecryptedPrivateKey = enc.isPresent();
138                        KeyPair pair = new KeyPair(this);
139                        validate(pair, assertDecryptedPrivateKey);
140                        return pair;
141                }
142
143        }
144
145}