/* This file is part of VoltDB. * Copyright (C) 2008-2017 VoltDB Inc. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with VoltDB. If not, see <http://www.gnu.org/licenses/>. */ package org.voltdb.utils; import java.io.File; import java.io.IOException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.validation.Schema; import javax.xml.validation.SchemaFactory; import org.voltdb.DependencyPair; import org.voltdb.compiler.deploymentfile.DeploymentType; import org.voltdb.compiler.deploymentfile.UsersType; import org.xml.sax.SAXException; public class CatalogPasswordScrambler { public static DeploymentType getDeployment(File sourceFH) { try { JAXBContext jc = JAXBContext.newInstance("org.voltdb.compiler.deploymentfile"); // This schema shot the sheriff. SchemaFactory sf = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = sf.newSchema( DependencyPair.class.getResource("compiler/DeploymentFileSchema.xsd") ); Unmarshaller unmarshaller = jc.createUnmarshaller(); unmarshaller.setSchema(schema); @SuppressWarnings("unchecked") JAXBElement<DeploymentType> result = (JAXBElement<DeploymentType>) unmarshaller.unmarshal(sourceFH); DeploymentType deployment = result.getValue(); return deployment; } catch (JAXBException e) { // Convert some linked exceptions to more friendly errors. if (e.getLinkedException() instanceof java.io.FileNotFoundException) { System.err.println(e.getLinkedException().getMessage()); return null; } else if (e.getLinkedException() instanceof org.xml.sax.SAXParseException) { System.err.println( "Error schema validating deployment.xml file. " + e.getLinkedException().getMessage() ); return null; } else { throw new RuntimeException(e); } } catch (SAXException e) { System.err.println("Error schema validating deployment.xml file. " + e.getMessage()); return null; } } public static void scramblePasswords(DeploymentType depl) { UsersType users = depl.getUsers(); if (users == null) return; for (UsersType.User user: users.getUser()) { if ( user.isPlaintext() && user.getPassword() != null && !user.getPassword().trim().isEmpty() ) { user.setPassword(Digester.shaAsHex(user.getPassword())); user.setPlaintext(false); } } } public static void writeOutMaskedDeploymentFile(DeploymentType depl, File maskedFH) { try { org.voltdb.compiler.deploymentfile.ObjectFactory factory = new org.voltdb.compiler.deploymentfile.ObjectFactory(); JAXBContext context = JAXBContext.newInstance(DeploymentType.class); JAXBElement<DeploymentType> doc = factory.createDeployment(depl); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); marshaller.marshal(doc, maskedFH); } catch (JAXBException e) { String msg = e.getMessage(); if (msg == null) msg = e.getLinkedException().getMessage(); System.err.println("Failed to write masked deployemnt: " + msg ); e.printStackTrace(); } } public static void main(String [] args) { if (args.length == 1) args = new String[] {args[0], args[0]}; if (args.length != 2) { System.out.println("Usage: CatalogPasswordScrambler [deployment-file-spec] [masked-deployment-file-spec]"); } File deployFH = new File(args[0]); if (!deployFH.exists() || !deployFH.isFile() || !deployFH.canRead()) { System.err.println("cannot access: "+ deployFH); } File maskedFH = new File(args[1]); try { File canonMaskedFH = maskedFH.getCanonicalFile(); File parentFH = canonMaskedFH.getParentFile(); if (!parentFH.exists() || !parentFH.isDirectory() || !parentFH.canWrite()) { System.err.println("do not have write access to " + parentFH); return; } } catch (IOException e) { System.err.println("could not stat specified files: " + e.getMessage()); return; } DeploymentType depl = getDeployment(deployFH); if (depl == null) return; try { scramblePasswords(depl); } catch (UnsupportedOperationException e) { System.err.println(e.getMessage()); return; } writeOutMaskedDeploymentFile(depl, maskedFH); } }