]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-2084 draft of new page 'Password encryption'
authorSimon Brandhof <simon.brandhof@gmail.com>
Tue, 13 Mar 2012 17:27:19 +0000 (18:27 +0100)
committerSimon Brandhof <simon.brandhof@gmail.com>
Tue, 13 Mar 2012 17:27:19 +0000 (18:27 +0100)
sonar-plugin-api/src/main/java/org/sonar/api/config/AesCipher.java
sonar-plugin-api/src/main/java/org/sonar/api/config/Encryption.java
sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java
sonar-server/src/main/webapp/WEB-INF/app/controllers/encryption_controller.rb [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/views/encryption/generate_secret.html.erb [new file with mode: 0644]
sonar-server/src/main/webapp/WEB-INF/app/views/encryption/index.html.erb [new file with mode: 0644]

index e8ed181966c8b205c1d0be5122a559a1de88b043..51232587bbddbaf73f82fabbc46140e65414521e 100644 (file)
@@ -32,7 +32,10 @@ import javax.crypto.SecretKey;
 import javax.crypto.spec.SecretKeySpec;
 import java.io.File;
 import java.io.IOException;
-import java.security.*;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
 import java.security.spec.InvalidKeySpecException;
 
 final class AesCipher extends Cipher {
@@ -45,10 +48,9 @@ final class AesCipher extends Cipher {
   }
 
   String encrypt(String clearText) {
-    String path = settings.getClearString(CoreProperties.ENCRYPTION_PATH_TO_SECRET_KEY);
     try {
       javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES");
-      cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, loadSecretFileFromFile(path));
+      cipher.init(javax.crypto.Cipher.ENCRYPT_MODE, loadSecretFile());
       return new String(Base64.encodeBase64(cipher.doFinal(clearText.getBytes(Charsets.UTF_8))));
     } catch (Exception e) {
       throw Throwables.propagate(e);
@@ -57,10 +59,9 @@ final class AesCipher extends Cipher {
 
 
   String decrypt(String encryptedText) {
-    String path = settings.getClearString(CoreProperties.ENCRYPTION_PATH_TO_SECRET_KEY);
     try {
       javax.crypto.Cipher cipher = javax.crypto.Cipher.getInstance("AES");
-      cipher.init(javax.crypto.Cipher.DECRYPT_MODE, loadSecretFileFromFile(path));
+      cipher.init(javax.crypto.Cipher.DECRYPT_MODE, loadSecretFile());
       byte[] cipherData = cipher.doFinal(Base64.decodeBase64(StringUtils.trim(encryptedText)));
       return new String(cipherData);
     } catch (Exception e) {
@@ -68,6 +69,19 @@ final class AesCipher extends Cipher {
     }
   }
 
+  public boolean canEncrypt() {
+    try {
+      return loadSecretFile() != null;
+    } catch (Exception e) {
+      return false;
+    }
+  }
+
+  Key loadSecretFile() throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, InvalidKeyException {
+    String path = settings.getClearString(CoreProperties.ENCRYPTION_PATH_TO_SECRET_KEY);
+    return loadSecretFileFromFile(path);
+  }
+
   @VisibleForTesting
   Key loadSecretFileFromFile(String path) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, InvalidKeyException {
     if (StringUtils.isBlank(path)) {
@@ -96,4 +110,6 @@ final class AesCipher extends Cipher {
       throw new IllegalStateException("Fail to generate random RSA keys", e);
     }
   }
+
+
 }
index def3164985fd19109b357315a2f341aef8f319d3..6cbc08d01d277360cb9140ea3d6394ecbf39992a 100644 (file)
@@ -49,6 +49,10 @@ public final class Encryption {
     );
   }
 
+  public boolean canEncrypt() {
+    return aesEncryption.canEncrypt();
+  }
+
   public boolean isEncrypted(String value) {
     return value.startsWith("{") && value.indexOf("}") > 1;
   }
index 8e88562a2bb4cf2adca883f6e6a7379585740753..57047d6585c9099864fb3220a275a31337e372ef 100644 (file)
@@ -52,6 +52,10 @@ public class Settings implements BatchComponent, ServerComponent {
     this.encryption = new Encryption(this);
   }
 
+  public final Encryption getEncryption() {
+    return encryption;
+  }
+
   public final String getDefaultValue(String key) {
     return definitions.getDefaultValue(key);
   }
index a497e03fcd30604c450e9b5b1f6de120d0d91e1d..0e7774cdf3443ad9b038bb493b9ec70ed725fb31 100644 (file)
@@ -399,6 +399,19 @@ public final class JRubyFacade {
     LoggerFactory.getLogger(getClass()).error(message);
   }
 
+  public boolean canEncrypt() {
+    return getContainer().getComponentByType(Settings.class).getEncryption().canEncrypt();
+  }
+
+  public String encrypt(String clearText) {
+    return getContainer().getComponentByType(Settings.class).getEncryption().encrypt(clearText);
+  }
+
+  public String generateRandomSecretKey() {
+    return getContainer().getComponentByType(Settings.class).getEncryption().generateRandomSecretKey();
+  }
+
+
   public ReviewsNotificationManager getReviewsNotificationManager() {
     return getContainer().getComponentByType(ReviewsNotificationManager.class);
   }
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/encryption_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/encryption_controller.rb
new file mode 100644 (file)
index 0000000..789b609
--- /dev/null
@@ -0,0 +1,47 @@
+#
+# Sonar, entreprise quality control tool.
+# Copyright (C) 2008-2012 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# Sonar is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# Sonar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with Sonar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
+#
+class EncryptionController < ApplicationController
+
+  SECTION=Navigation::SECTION_CONFIGURATION
+  before_filter :admin_required
+  verify :method => :post, :only => [:generate_secret, :encrypt], :redirect_to => {:action => :index}
+
+  def index
+    @can_encrypt=java_facade.canEncrypt()
+  end
+
+  def generate_secret
+    begin
+      @secret=java_facade.generateRandomSecretKey()
+    rescue Exception => e
+      flash[:error]=e.message
+      redirect_to :action => :index
+    end
+  end
+
+  def encrypt
+    bad_request('No secret key') unless java_facade.canEncrypt()
+    @encrypted=java_facade.encrypt(params[:text])
+  end
+
+  private
+
+
+end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/encryption/generate_secret.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/encryption/generate_secret.html.erb
new file mode 100644 (file)
index 0000000..7323895
--- /dev/null
@@ -0,0 +1,4 @@
+<p>
+  Secret is:
+  <input type="text" value="<%= @secret -%>"/>
+</p>
\ No newline at end of file
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/views/encryption/index.html.erb b/sonar-server/src/main/webapp/WEB-INF/app/views/encryption/index.html.erb
new file mode 100644 (file)
index 0000000..06fd70d
--- /dev/null
@@ -0,0 +1,12 @@
+<p>bla bla</p>
+
+<% if @can_encrypt %>
+  <form action="<%= ApplicationController.root_context -%>/encryption/encrypt" method="POST">
+    <input type="text" name="text" id="text"/>
+    <input type="submit" value="Encrypt" id="submit_encrypt"/>
+  </form>
+<% else %>
+  <form action="<%= ApplicationController.root_context -%>/encryption/generate_secret" method="POST">
+    <input type="submit" value="Generate secret" id="submit_generate_secret"/>
+  </form>
+<% end %>
\ No newline at end of file