001/** 002 * Copyright 2010-2014 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.common.util.enc; 017 018import java.util.List; 019 020import org.jasypt.util.text.TextEncryptor; 021import org.kuali.common.util.Assert; 022import org.kuali.common.util.PropertyUtils; 023import org.kuali.common.util.Str; 024import org.kuali.common.util.spring.SpringUtils; 025import org.kuali.common.util.spring.env.BasicEnvironmentService; 026import org.kuali.common.util.spring.env.EnvUtils; 027import org.kuali.common.util.spring.env.EnvironmentService; 028 029import com.google.common.base.Optional; 030import com.google.common.collect.ImmutableList; 031 032/** 033 * @deprecated Use EncContext instead 034 */ 035@Deprecated 036public final class EncContext { 037 038 private final Optional<TextEncryptor> textEncryptor; 039 private final EncStrength strength; 040 041 private EncContext(Builder builder) { 042 this.strength = builder.strength; 043 this.textEncryptor = builder.textEncryptor; 044 } 045 046 public Optional<TextEncryptor> getTextEncryptor() { 047 return textEncryptor; 048 } 049 050 public EncStrength getStrength() { 051 return strength; 052 } 053 054 public static Builder builder(String password) { 055 return new Builder(password); 056 } 057 058 public static Builder builder(EnvironmentService env) { 059 return new Builder(env); 060 } 061 062 public static class Builder { 063 064 // Required (but optional) 065 private final Optional<String> password; 066 private final Optional<EnvironmentService> env; 067 068 // Optional 069 private Optional<TextEncryptor> textEncryptor = Optional.absent(); 070 private EncStrength strength = EncStrength.BASIC; 071 private boolean required = false; 072 private boolean removeSystemProperties = false; 073 074 private static final List<String> PASSWORD_KEYS = ImmutableList.of("enc.password", "properties.enc.password"); 075 private static final List<String> STRENGTH_KEYS = ImmutableList.of("enc.strength", "properties.enc.strength"); 076 private static final List<String> PASSWORD_REQUIRED_KEYS = ImmutableList.of("enc.password.required", "properties.decrypt"); 077 private static final String PASSWORD_REMOVE_KEY = "enc.password.removeSystemProperty"; 078 079 /** 080 * Setup encryption using <code>password</code> 081 */ 082 public Builder(String password) { 083 this(EnvUtils.ABSENT, Optional.of(password)); 084 } 085 086 /** 087 * Use the password they gave us, unless it is overridden by a password in the environment 088 */ 089 public Builder(EnvironmentService env, String password) { 090 this(Optional.of(env), Optional.of(password)); 091 } 092 093 /** 094 * Use system properties / environment variables to locate the encryption password 095 */ 096 public Builder() { 097 this(new BasicEnvironmentService()); 098 } 099 100 /** 101 * Locate the encryption password in the environment 102 */ 103 public Builder(EnvironmentService env) { 104 this(Optional.of(env), Optional.<String> absent()); 105 } 106 107 private Builder(Optional<EnvironmentService> env, Optional<String> password) { 108 if (env.isPresent()) { 109 this.password = SpringUtils.getString(env, PASSWORD_KEYS, password); 110 } else { 111 this.password = password; 112 } 113 this.env = env; 114 } 115 116 public Builder removeSystemProperties(boolean removeSystemProperties) { 117 this.removeSystemProperties = removeSystemProperties; 118 return this; 119 } 120 121 public Builder required(boolean required) { 122 this.required = required; 123 return this; 124 } 125 126 public Builder strength(EncStrength strength) { 127 this.strength = strength; 128 return this; 129 } 130 131 private void override() { 132 if (env.isPresent()) { 133 strength(SpringUtils.getProperty(env, STRENGTH_KEYS, EncStrength.class, strength)); 134 required(SpringUtils.getProperty(env, PASSWORD_REQUIRED_KEYS, Boolean.class, required)); 135 removeSystemProperties(env.get().getBoolean(PASSWORD_REMOVE_KEY, removeSystemProperties)); 136 } 137 } 138 139 private void validate(EncContext ctx, boolean required, Optional<String> password) { 140 Assert.notNull(ctx.getTextEncryptor(), "'textEncryptor' cannot be null"); 141 Assert.notNull(ctx.getStrength(), "'strength' cannot be null"); 142 if (required) { 143 Assert.isTrue(ctx.getTextEncryptor().isPresent()); 144 } 145 if (password.isPresent()) { 146 Assert.noBlanks(password.get()); 147 Assert.notEncrypted(password.get()); 148 Assert.notConcealed(password.get()); 149 } 150 } 151 152 private void finish() { 153 override(); 154 if (password.isPresent()) { 155 String revealed = Str.reveal(password.get()); 156 TextEncryptor enc = EncUtils.getTextEncryptor(revealed, strength); 157 this.textEncryptor = Optional.of(enc); 158 } 159 } 160 161 public EncContext build() { 162 // Finish setting up the builder 163 finish(); 164 165 // Get local references to builder instance variables 166 boolean required = this.required; 167 boolean removeSystemProperties = this.removeSystemProperties; 168 Optional<String> password = Optional.fromNullable(this.password.orNull()); 169 170 // Construct the encryption context 171 EncContext ctx = new EncContext(this); 172 173 // Validate that it's in good shape 174 validate(ctx, required, password); 175 176 // Now that we've successfully created and validated the instance, it's safe to remove the system properties 177 if (removeSystemProperties) { 178 PropertyUtils.removeSystemProperties(PASSWORD_KEYS); 179 } 180 181 // Return the context 182 return ctx; 183 } 184 185 } 186 187}