/* * Copyright (c) 2014 EMC Corporation * All Rights Reserved */ package com.emc.storageos.security.keystore.impl; import com.emc.storageos.coordinator.client.service.CoordinatorClient; import com.emc.storageos.security.keystore.KeyStoreExporter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.attribute.GroupPrincipal; import java.nio.file.attribute.PosixFileAttributeView; import java.nio.file.attribute.PosixFilePermission; import java.nio.file.attribute.UserPrincipal; import java.nio.file.attribute.UserPrincipalLookupService; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.util.HashSet; import java.util.Set; /** * Implementation class for KeyStoreExporter interface */ public class KeyStoreExporterImpl implements KeyStoreExporter { private static final Logger log = LoggerFactory.getLogger(KeyStoreExporterImpl.class); private static final String STORAGEOS_NAME = "storageos"; private static final String FILE_LOCK_PATH = "/tmp/keystorelock"; @Autowired private CoordinatorClient coordinator; private String keystorePath; private String keystorePassword; private String owner = STORAGEOS_NAME; private String group = STORAGEOS_NAME; private RandomAccessFile lockFile; private FileChannel lockChannel; private FileLock lock; public KeyStoreExporterImpl() { } public void setCoordinator(CoordinatorClient coordinator) { this.coordinator = coordinator; } public void setKeystorePath(String keystorePath) { this.keystorePath = keystorePath; } public void setKeystorePassword(String keystorePassword) { this.keystorePassword = keystorePassword; } public void setOwner(String owner) { this.owner = owner; } public void setOwnerGroup(String groupName) { this.group = groupName; } @Override public void export() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, InterruptedException { log.info("Start exporting keyStore to local file {}", keystorePath); lock(); try { if (isKeystoreFileValid()) { log.info("Keystore file {} found, no need to generate again.", keystorePath); return; } saveKeystore(); setKeyStorePermission(); } finally { unlock(); } log.info("Exported keystore successfully"); } private void lock() throws IOException { lockFile = new RandomAccessFile(FILE_LOCK_PATH, "rw"); lockChannel = lockFile.getChannel(); lock = lockChannel.lock(); log.info("Acquired lock successfully"); } private void unlock() throws IOException { try { lock.release(); } finally { lockChannel.close(); lockFile.close(); } log.info("Released lock"); } private boolean isKeystoreFileValid() { File keystoreFile = new File(keystorePath); return keystoreFile.exists() && keystoreFile.length() > 0; } private void saveKeystore() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, InterruptedException { KeyStore keyStore = KeyStoreUtil.getViPRKeystore(coordinator); FileOutputStream stream = null; try { stream = new FileOutputStream(keystorePath); keyStore.store(stream, keystorePassword.toCharArray()); } finally { if (stream != null) { stream.close(); } } } /** * Set owner and file permission for the keystore file */ private void setKeyStorePermission() throws IOException { Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>(); perms.add(PosixFilePermission.OWNER_READ); File keystoreFile = new File(keystorePath); setFilePermissions(keystoreFile.toPath(), owner, group, perms); } /** * Sets the file permissions on the specified path. The group of the file is the * user's group * * @param path the path for which to set permissions * @param owner the owner of the specified path * @param group group name of the specified path * @param permissions the permissions to set */ private void setFilePermissions(Path path, String owner, String groupName, Set<PosixFilePermission> permissions) throws IOException { UserPrincipalLookupService lookupService = FileSystems.getDefault().getUserPrincipalLookupService(); UserPrincipal user = lookupService.lookupPrincipalByName(owner); GroupPrincipal group = lookupService.lookupPrincipalByGroupName(groupName); PosixFileAttributeView attributeView = Files.getFileAttributeView(path, PosixFileAttributeView.class); attributeView.setGroup(group); attributeView.setOwner(user); Files.setPosixFilePermissions(path, permissions); } }